mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
1be93b54a9
|
@ -703,6 +703,10 @@ namespace triagens {
|
|||
if (_done) {
|
||||
return nullptr;
|
||||
}
|
||||
std::cout << _depth << " ";
|
||||
for (auto i: _varOverview->nrRegs)
|
||||
std::cout << i << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
AqlItemBlock* res = new AqlItemBlock(1, _varOverview->nrRegs[_depth]);
|
||||
if (_inputRegisterValues != nullptr) {
|
||||
|
@ -1475,21 +1479,44 @@ namespace triagens {
|
|||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < res->size(); i++) {
|
||||
_subquery->initialize();
|
||||
_subquery->bind(res, i);
|
||||
_subquery->execute();
|
||||
auto results = new std::vector<AqlItemBlock*>;
|
||||
do {
|
||||
auto tmp = _subquery->getSome(DefaultBatchSize, DefaultBatchSize);
|
||||
if (tmp == nullptr) {
|
||||
break;
|
||||
}
|
||||
results->push_back(tmp);
|
||||
int ret;
|
||||
ret = _subquery->initialize();
|
||||
if (ret == TRI_ERROR_NO_ERROR) {
|
||||
ret = _subquery->bind(res, i);
|
||||
}
|
||||
if (ret == TRI_ERROR_NO_ERROR) {
|
||||
ret = _subquery->execute();
|
||||
}
|
||||
if (ret != TRI_ERROR_NO_ERROR) {
|
||||
delete res;
|
||||
THROW_ARANGO_EXCEPTION(ret);
|
||||
}
|
||||
|
||||
auto results = new std::vector<AqlItemBlock*>;
|
||||
try {
|
||||
do {
|
||||
auto tmp = _subquery->getSome(DefaultBatchSize, DefaultBatchSize);
|
||||
if (tmp == nullptr) {
|
||||
break;
|
||||
}
|
||||
results->push_back(tmp);
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
catch (...) {
|
||||
delete res;
|
||||
delete results;
|
||||
throw;
|
||||
}
|
||||
while(true);
|
||||
|
||||
res->setValue(i, _outReg, AqlValue(results));
|
||||
_subquery->shutdown();
|
||||
|
||||
ret = _subquery->shutdown();
|
||||
if (ret != TRI_ERROR_NO_ERROR) {
|
||||
delete res;
|
||||
THROW_ARANGO_EXCEPTION(ret);
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1805,29 +1832,6 @@ namespace triagens {
|
|||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
/*
|
||||
void emitRow (AqlItemBlock* res,
|
||||
size_t j,
|
||||
AqlItemBlock* cur,
|
||||
void* row) {
|
||||
std::cout << "EMIT ROW: " << j << "\n";
|
||||
|
||||
if (j == 0) {
|
||||
// first row in block
|
||||
TRI_ASSERT(cur->getNrRegs() <= res->getNrRegs());
|
||||
|
||||
inheritRegisters(cur, res, _pos);
|
||||
}
|
||||
|
||||
for (auto it = _aggregateRegisters.begin(); it != _aggregateRegisters.end(); ++it) {
|
||||
// TODO: return the actual group values
|
||||
res->setValue(j, (*it).first, AqlValue(new basics::Json(42)));
|
||||
}
|
||||
|
||||
clearGroup();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getSome
|
||||
|
@ -1874,9 +1878,11 @@ std::cout << "POS: " << _pos << "\n";
|
|||
if (_currentGroup.groupValues[0].isEmpty()) {
|
||||
// we never had any previous group
|
||||
newGroup = true;
|
||||
std::cout << "NEED TO CREATE NEW GROUP\n";
|
||||
}
|
||||
else {
|
||||
// we already had a group, check if the group has changed
|
||||
std::cout << "HAVE A GROUP\n";
|
||||
size_t i = 0;
|
||||
|
||||
for (auto it = _aggregateRegisters.begin(); it != _aggregateRegisters.end(); ++it) {
|
||||
|
@ -1894,13 +1900,18 @@ std::cout << "POS: " << _pos << "\n";
|
|||
}
|
||||
|
||||
if (newGroup) {
|
||||
std::cout << "CREATING GROUP...\n";
|
||||
if (! _currentGroup.groupValues[0].isEmpty()) {
|
||||
// need to emit the current group first
|
||||
std::cout << "EMITTING OLD GROUP INTO ROW #" << j << "\n";
|
||||
size_t i = 0;
|
||||
for (auto it = _aggregateRegisters.begin(); it != _aggregateRegisters.end(); ++it) {
|
||||
std::cout << "REGISTER #" << (*it).first << "\n";
|
||||
res->setValue(j, (*it).first, _currentGroup.groupValues[i]);
|
||||
++i;
|
||||
}
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
// construct the new group
|
||||
|
@ -1908,7 +1919,7 @@ std::cout << "POS: " << _pos << "\n";
|
|||
for (auto it = _aggregateRegisters.begin(); it != _aggregateRegisters.end(); ++it) {
|
||||
_currentGroup.groupValues[i] = cur->getValue(_pos, (*it).second).clone();
|
||||
_currentGroup.collections[i] = cur->getDocumentCollection((*it).second);
|
||||
// std::cout << "GROUP VALUE #" << i << ": " << _currentGroup.groupValues[i].toString(_currentGroup.collections[i]) << "\n";
|
||||
std::cout << "GROUP VALUE #" << i << ": " << _currentGroup.groupValues[i].toString(_currentGroup.collections[i]) << "\n";
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -1917,16 +1928,19 @@ std::cout << "POS: " << _pos << "\n";
|
|||
// _currentGroup.groupDetails.
|
||||
}
|
||||
|
||||
++j;
|
||||
|
||||
if (++_pos >= cur->size()) {
|
||||
_buffer.pop_front();
|
||||
delete cur;
|
||||
_pos = 0;
|
||||
std::cout << "SHRINKING BLOCK TO " << j << " ROWS\n";
|
||||
res->shrink(j);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "SHRINKING BLOCK TO " << j << " ROWS\n";
|
||||
res->shrink(j);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,14 +123,41 @@ v8::Handle<v8::Value> AqlValue::toV8 (AQL_TRANSACTION_V8* trx,
|
|||
}
|
||||
|
||||
case DOCVEC: {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
// calculate the result list length
|
||||
size_t totalSize = 0;
|
||||
for (auto it = _vector->begin(); it != _vector->end(); ++it) {
|
||||
totalSize += (*it)->size();
|
||||
}
|
||||
|
||||
// allocate the result list
|
||||
v8::Handle<v8::Array> result = v8::Array::New(static_cast<int>(totalSize));
|
||||
uint32_t j = 0; // output row count
|
||||
|
||||
for (auto it = _vector->begin(); it != _vector->end(); ++it) {
|
||||
auto current = (*it);
|
||||
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(trx, vecCollection));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
case RANGE: {
|
||||
v8::Handle<v8::Array> values = v8::Array::New();
|
||||
// TODO: fill range
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
return values;
|
||||
TRI_ASSERT(_range != nullptr);
|
||||
|
||||
// allocate the buffer for the result
|
||||
int64_t const n = _range->_high - _range->_low + 1;
|
||||
v8::Handle<v8::Array> result = v8::Array::New(static_cast<int>(n));
|
||||
|
||||
uint32_t j = 0; // output row count
|
||||
for (int64_t i = _range->_low; i <= _range->_high; ++i) {
|
||||
// is it safe to use a double here (precision loss)?
|
||||
result->Set(j++, v8::Number::New(static_cast<double>(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case EMPTY: {
|
||||
|
@ -281,6 +308,7 @@ AqlItemBlock* AqlItemBlock::splice (std::vector<AqlItemBlock*>& blocks) {
|
|||
}
|
||||
pos += (*it)->size();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -288,101 +316,111 @@ AqlItemBlock* AqlItemBlock::splice (std::vector<AqlItemBlock*>& blocks) {
|
|||
/// @brief 3-way comparison for AqlValue objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int triagens::aql::CompareAqlValues ( AqlValue const& left,
|
||||
TRI_document_collection_t const* leftcoll,
|
||||
AqlValue const& right,
|
||||
TRI_document_collection_t const* rightcoll ) {
|
||||
int triagens::aql::CompareAqlValues (AqlValue const& left,
|
||||
TRI_document_collection_t const* leftcoll,
|
||||
AqlValue const& right,
|
||||
TRI_document_collection_t const* rightcoll) {
|
||||
if (left._type != right._type) {
|
||||
if (left._type == AqlValue::EMPTY) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (left._type != right._type) {
|
||||
if (left._type == AqlValue::EMPTY) {
|
||||
return -1;
|
||||
}
|
||||
if (right._type == AqlValue::EMPTY) {
|
||||
return 1;
|
||||
}
|
||||
if (left._type == AqlValue::JSON && right._type == AqlValue::SHAPED) {
|
||||
triagens::basics::Json rjson = right.toJson(rightcoll);
|
||||
return TRI_CompareValuesJson(left._json->json(), rjson.json());
|
||||
}
|
||||
if (left._type == AqlValue::SHAPED && right._type == AqlValue::JSON) {
|
||||
triagens::basics::Json ljson = left.toJson(leftcoll);
|
||||
return TRI_CompareValuesJson(ljson.json(), right._json->json());
|
||||
}
|
||||
// No other comparisons are defined
|
||||
TRI_ASSERT(false);
|
||||
if (right._type == AqlValue::EMPTY) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (left._type == AqlValue::JSON && right._type == AqlValue::SHAPED) {
|
||||
triagens::basics::Json rjson = right.toJson(rightcoll);
|
||||
return TRI_CompareValuesJson(left._json->json(), rjson.json());
|
||||
}
|
||||
|
||||
if (left._type == AqlValue::SHAPED && right._type == AqlValue::JSON) {
|
||||
triagens::basics::Json ljson = left.toJson(leftcoll);
|
||||
return TRI_CompareValuesJson(ljson.json(), right._json->json());
|
||||
}
|
||||
|
||||
// No other comparisons are defined
|
||||
TRI_ASSERT(false);
|
||||
}
|
||||
|
||||
// if we get here, types are equal
|
||||
|
||||
switch (left._type) {
|
||||
case AqlValue::EMPTY: {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case AqlValue::JSON: {
|
||||
return TRI_CompareValuesJson(left._json->json(), right._json->json());
|
||||
}
|
||||
|
||||
case AqlValue::SHAPED: {
|
||||
TRI_shaped_json_t l;
|
||||
TRI_shaped_json_t r;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(l, left._marker);
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(r, right._marker);
|
||||
|
||||
return TRI_CompareShapeTypes(nullptr, nullptr, &l, leftcoll->getShaper(),
|
||||
nullptr, nullptr, &r, rightcoll->getShaper());
|
||||
}
|
||||
|
||||
case AqlValue::DOCVEC: {
|
||||
// use lexicographic ordering of AqlValues regardless of block,
|
||||
// DOCVECs have a single register coming from ReturnNode.
|
||||
size_t lblock = 0;
|
||||
size_t litem = 0;
|
||||
size_t rblock = 0;
|
||||
size_t ritem = 0;
|
||||
|
||||
while (lblock < left._vector->size() &&
|
||||
rblock < right._vector->size()) {
|
||||
AqlValue lval = left._vector->at(lblock)->getValue(litem, 0);
|
||||
AqlValue rval = right._vector->at(rblock)->getValue(ritem, 0);
|
||||
int cmp = CompareAqlValues(lval,
|
||||
left._vector->at(lblock)->getDocumentCollection(0),
|
||||
rval,
|
||||
right._vector->at(rblock)->getDocumentCollection(0));
|
||||
if (cmp != 0){
|
||||
return cmp;
|
||||
}
|
||||
switch (left._type) {
|
||||
case AqlValue::EMPTY: {
|
||||
return 0;
|
||||
}
|
||||
case AqlValue::JSON: {
|
||||
return TRI_CompareValuesJson(left._json->json(), right._json->json());
|
||||
}
|
||||
case AqlValue::SHAPED: {
|
||||
TRI_shaped_json_t l;
|
||||
TRI_shaped_json_t r;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(l, left._marker);
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(r, right._marker);
|
||||
|
||||
return TRI_CompareShapeTypes(nullptr, nullptr, &l, leftcoll->getShaper(),
|
||||
nullptr, nullptr, &r, rightcoll->getShaper());
|
||||
}
|
||||
case AqlValue::DOCVEC: {
|
||||
// use lexicographic ordering of AqlValues regardless of block,
|
||||
// DOCVECs have a single register coming from ReturnNode.
|
||||
size_t lblock = 0;
|
||||
size_t litem = 0;
|
||||
size_t rblock = 0;
|
||||
size_t ritem = 0;
|
||||
|
||||
while( lblock < left._vector->size() && rblock < right._vector->size() ){
|
||||
AqlValue lval = left._vector->at(lblock)->getValue(litem, 0);
|
||||
AqlValue rval = right._vector->at(rblock)->getValue(ritem, 0);
|
||||
int cmp = CompareAqlValues(lval,
|
||||
left._vector->at(lblock)->getDocumentCollection(0),
|
||||
rval,
|
||||
right._vector->at(rblock)->getDocumentCollection(0));
|
||||
if(cmp != 0){
|
||||
return cmp;
|
||||
}
|
||||
if(++litem == left._vector->size()){
|
||||
litem = 0;
|
||||
lblock++;
|
||||
}
|
||||
if(++ritem == right._vector->size()){
|
||||
ritem = 0;
|
||||
rblock++;
|
||||
}
|
||||
}
|
||||
|
||||
if(lblock == left._vector->size() && rblock == right._vector->size()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (lblock < left._vector->size()?-1:1);
|
||||
}
|
||||
case AqlValue::RANGE: {
|
||||
if(left._range->_low < right._range->_low){
|
||||
return -1;
|
||||
}
|
||||
if (left._range->_low > right._range->_low){
|
||||
return 1;
|
||||
}
|
||||
if (left._range->_high < left._range->_high) {
|
||||
return -1;
|
||||
}
|
||||
if (left._range->_high > left._range->_high) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
default: {
|
||||
TRI_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
if (++litem == left._vector->size()) {
|
||||
litem = 0;
|
||||
lblock++;
|
||||
}
|
||||
if (++ritem == right._vector->size()) {
|
||||
ritem = 0;
|
||||
rblock++;
|
||||
}
|
||||
}
|
||||
|
||||
if (lblock == left._vector->size() &&
|
||||
rblock == right._vector->size()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (lblock < left._vector->size() ? -1 : 1);
|
||||
}
|
||||
case AqlValue::RANGE: {
|
||||
if (left._range->_low < right._range->_low){
|
||||
return -1;
|
||||
}
|
||||
if (left._range->_low > right._range->_low){
|
||||
return 1;
|
||||
}
|
||||
if (left._range->_high < left._range->_high) {
|
||||
return -1;
|
||||
}
|
||||
if (left._range->_high > left._range->_high) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
default: {
|
||||
TRI_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
|
|
|
@ -330,9 +330,11 @@ namespace triagens {
|
|||
|
||||
~AqlItemBlock () {
|
||||
std::unordered_set<AqlValue> cache;
|
||||
|
||||
for (size_t i = 0; i < _nrItems * _nrRegs; i++) {
|
||||
if (! _data[i].isEmpty()) {
|
||||
auto it = cache.find(_data[i]);
|
||||
|
||||
if (it == cache.end()) {
|
||||
cache.insert(_data[i]);
|
||||
_data[i].destroy();
|
||||
|
@ -341,20 +343,46 @@ namespace triagens {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shrink the block to the specified number of rows
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void shrink (size_t nrItems) {
|
||||
if (nrItems == _nrItems) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
if (nrItems > _nrItems) {
|
||||
// cannot use shrink() to increase the size of the block
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
// erase all stored values in the region that we freed
|
||||
for (size_t i = nrItems; i < _nrItems; ++i) {
|
||||
for (RegisterId j = 0; j < _nrRegs; ++j) {
|
||||
eraseValue(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
// adjust the size of the block
|
||||
_nrItems = nrItems;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getValue, get the value of a register
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue getValue (size_t index, RegisterId varNr) const {
|
||||
return _data[index * _nrRegs + varNr];
|
||||
}
|
||||
AqlValue getValue (size_t index, RegisterId varNr) const {
|
||||
return _data[index * _nrRegs + varNr];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setValue, set the current value of a register
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setValue (size_t index, RegisterId varNr, AqlValue value) {
|
||||
TRI_ASSERT(_data[index * _nrRegs + varNr].isEmpty());
|
||||
TRI_ASSERT(_data.capacity() > index * _nrRegs + varNr);
|
||||
TRI_ASSERT(_data.at(index * _nrRegs + varNr).isEmpty());
|
||||
_data[index * _nrRegs + varNr] = value;
|
||||
}
|
||||
|
||||
|
@ -363,121 +391,141 @@ namespace triagens {
|
|||
/// this is used if the value is stolen and later released from elsewhere
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void eraseValue (size_t index, RegisterId varNr) {
|
||||
_data[index * _nrRegs + varNr].erase();
|
||||
}
|
||||
void eraseValue (size_t index, RegisterId varNr) {
|
||||
_data[index * _nrRegs + varNr].erase();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getDocumentCollection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_document_collection_t const* getDocumentCollection (RegisterId varNr) const {
|
||||
return _docColls[varNr];
|
||||
}
|
||||
TRI_document_collection_t const* getDocumentCollection (RegisterId varNr) const {
|
||||
return _docColls[varNr];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setDocumentCollection, set the current value of a variable or attribute
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setDocumentCollection (RegisterId varNr, TRI_document_collection_t const* docColl) {
|
||||
_docColls[varNr] = docColl;
|
||||
}
|
||||
void setDocumentCollection (RegisterId varNr, TRI_document_collection_t const* docColl) {
|
||||
_docColls[varNr] = docColl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getter for _nrRegs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RegisterId getNrRegs () const {
|
||||
return _nrRegs;
|
||||
}
|
||||
RegisterId getNrRegs () const {
|
||||
return _nrRegs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getter for _nrItems
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t size () const {
|
||||
return _nrItems;
|
||||
}
|
||||
size_t size () const {
|
||||
return _nrItems;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getter for _data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<AqlValue>& getData () {
|
||||
return _data;
|
||||
}
|
||||
vector<AqlValue>& getData () {
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getter for _docColls
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<TRI_document_collection_t const*>& getDocumentCollections () {
|
||||
return _docColls;
|
||||
}
|
||||
vector<TRI_document_collection_t const*>& getDocumentCollections () {
|
||||
return _docColls;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief slice/clone
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlItemBlock* slice (size_t from, size_t to) {
|
||||
TRI_ASSERT(from < to && to <= _nrItems);
|
||||
AqlItemBlock* slice (size_t from, size_t to) {
|
||||
TRI_ASSERT(from < to && to <= _nrItems);
|
||||
|
||||
std::unordered_map<AqlValue, AqlValue> cache;
|
||||
auto res = new AqlItemBlock(to - from, _nrRegs);
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
res->_docColls[col] = _docColls[col];
|
||||
}
|
||||
for (size_t row = from; row < to; row++) {
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
AqlValue& a(_data[row * _nrRegs + col]);
|
||||
std::unordered_map<AqlValue, AqlValue> cache;
|
||||
|
||||
if (! a.isEmpty()) {
|
||||
auto it = cache.find(a);
|
||||
if (it == cache.end()) {
|
||||
AqlValue b = a.clone();
|
||||
res->_data[(row - from) * _nrRegs + col] = b;
|
||||
cache.insert(make_pair(a,b));
|
||||
}
|
||||
else {
|
||||
res->_data[(row - from) * _nrRegs + col] = it->second;
|
||||
AqlItemBlock* res = nullptr;
|
||||
try {
|
||||
res = new AqlItemBlock(to - from, _nrRegs);
|
||||
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
res->_docColls[col] = _docColls[col];
|
||||
}
|
||||
for (size_t row = from; row < to; row++) {
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
AqlValue& a(_data[row * _nrRegs + col]);
|
||||
|
||||
if (! a.isEmpty()) {
|
||||
auto it = cache.find(a);
|
||||
if (it == cache.end()) {
|
||||
AqlValue b = a.clone();
|
||||
res->_data[(row - from) * _nrRegs + col] = b;
|
||||
cache.insert(make_pair(a,b));
|
||||
}
|
||||
else {
|
||||
res->_data[(row - from) * _nrRegs + col] = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
catch (...) {
|
||||
delete res;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief slice/clone for a subset
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlItemBlock* slice (vector<size_t>& chosen, size_t from, size_t to) {
|
||||
TRI_ASSERT(from < to && to <= chosen.size());
|
||||
AqlItemBlock* slice (vector<size_t>& chosen, size_t from, size_t to) {
|
||||
TRI_ASSERT(from < to && to <= chosen.size());
|
||||
|
||||
std::unordered_map<AqlValue, AqlValue> cache;
|
||||
auto res = new AqlItemBlock(to - from, _nrRegs);
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
res->_docColls[col] = _docColls[col];
|
||||
}
|
||||
for (size_t row = from; row < to; row++) {
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
AqlValue& a(_data[chosen[row] * _nrRegs + col]);
|
||||
std::unordered_map<AqlValue, AqlValue> cache;
|
||||
|
||||
if (! a.isEmpty()) {
|
||||
auto it = cache.find(a);
|
||||
if (it == cache.end()) {
|
||||
AqlValue b = a.clone();
|
||||
res->_data[(row - from) * _nrRegs + col] = b;
|
||||
cache.insert(make_pair(a,b));
|
||||
}
|
||||
else {
|
||||
res->_data[(row - from) * _nrRegs + col] = it->second;
|
||||
AqlItemBlock* res = nullptr;
|
||||
try {
|
||||
res = new AqlItemBlock(to - from, _nrRegs);
|
||||
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
res->_docColls[col] = _docColls[col];
|
||||
}
|
||||
for (size_t row = from; row < to; row++) {
|
||||
for (RegisterId col = 0; col < _nrRegs; col++) {
|
||||
AqlValue& a(_data[chosen[row] * _nrRegs + col]);
|
||||
|
||||
if (! a.isEmpty()) {
|
||||
auto it = cache.find(a);
|
||||
if (it == cache.end()) {
|
||||
AqlValue b = a.clone();
|
||||
res->_data[(row - from) * _nrRegs + col] = b;
|
||||
cache.insert(make_pair(a,b));
|
||||
}
|
||||
else {
|
||||
res->_data[(row - from) * _nrRegs + col] = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
catch (...) {
|
||||
delete res;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief splice multiple blocks, note that the new block now owns all
|
||||
|
@ -485,7 +533,7 @@ namespace triagens {
|
|||
/// set to nullptr, just to be sure.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static AqlItemBlock* splice(std::vector<AqlItemBlock*>& blocks);
|
||||
static AqlItemBlock* splice (std::vector<AqlItemBlock*>& blocks);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -35,13 +35,17 @@
|
|||
|
||||
#include "Ahuacatl/ahuacatl-collections.h"
|
||||
#include "Ahuacatl/ahuacatl-explain.h"
|
||||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Basics/Utf8Helper.h"
|
||||
#include "HttpServer/ApplicationEndpointServer.h"
|
||||
|
||||
#include "BasicsC/conversions.h"
|
||||
#include "BasicsC/json-utilities.h"
|
||||
#include "Utils/transactions.h"
|
||||
#include "Utils/AhuacatlGuard.h"
|
||||
#include "Utils/AhuacatlTransaction.h"
|
||||
#include "Utils/V8ResolverGuard.h"
|
||||
|
||||
#include "HttpServer/ApplicationEndpointServer.h"
|
||||
#include "V8/v8-conv.h"
|
||||
#include "V8/v8-execution.h"
|
||||
#include "V8/v8-utils.h"
|
||||
|
|
Loading…
Reference in New Issue