mirror of https://gitee.com/bigwinds/arangodb
less copying of RangeInfoBounds
This commit is contained in:
parent
6f4fadd630
commit
3f913f96d7
|
@ -999,7 +999,8 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine,
|
||||||
_condition(new IndexOrCondition()),
|
_condition(new IndexOrCondition()),
|
||||||
_posInRanges(0),
|
_posInRanges(0),
|
||||||
_sortCoords(),
|
_sortCoords(),
|
||||||
_freeCondition(true) {
|
_freeCondition(true),
|
||||||
|
_hasV8Expression(false) {
|
||||||
|
|
||||||
auto trxCollection = _trx->trxCollection(_collection->cid());
|
auto trxCollection = _trx->trxCollection(_collection->cid());
|
||||||
if (trxCollection != nullptr) {
|
if (trxCollection != nullptr) {
|
||||||
|
@ -1031,7 +1032,7 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine,
|
||||||
isConstant &= r.isConstant();
|
isConstant &= r.isConstant();
|
||||||
}
|
}
|
||||||
_anyBoundVariable |= ! isConstant;
|
_anyBoundVariable |= ! isConstant;
|
||||||
_allBoundsConstant.push_back(isConstant);
|
_allBoundsConstant.emplace_back(isConstant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,6 +1054,191 @@ IndexRangeBlock::~IndexRangeBlock () {
|
||||||
delete _edgeIndexIterator;
|
delete _edgeIndexIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IndexRangeBlock::hasV8Expression () const {
|
||||||
|
for (auto expression : _allVariableBoundExpressions) {
|
||||||
|
TRI_ASSERT(expression != nullptr);
|
||||||
|
if (expression->isV8()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexRangeBlock::buildExpressions () {
|
||||||
|
auto en = static_cast<IndexRangeNode const*>(getPlanNode());
|
||||||
|
size_t posInExpressions = 0;
|
||||||
|
|
||||||
|
// The following are needed to evaluate expressions with local data from
|
||||||
|
// the current incoming item:
|
||||||
|
AqlItemBlock* cur = _buffer.front();
|
||||||
|
vector<AqlValue>& data(cur->getData());
|
||||||
|
vector<TRI_document_collection_t const*>& docColls(cur->getDocumentCollections());
|
||||||
|
RegisterId nrRegs = cur->getNrRegs();
|
||||||
|
|
||||||
|
|
||||||
|
IndexOrCondition* newCondition = nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < en->_ranges.size(); i++) {
|
||||||
|
size_t const n = en->_ranges[i].size();
|
||||||
|
// prefill with n default-constructed vectors
|
||||||
|
std::vector<std::vector<RangeInfo>> collector(n);
|
||||||
|
|
||||||
|
// collect the evaluated bounds here
|
||||||
|
for (size_t k = 0; k < n; k++) {
|
||||||
|
auto r = en->_ranges[i][k];
|
||||||
|
// First create a new RangeInfo containing only the constant
|
||||||
|
// low and high bound of r:
|
||||||
|
RangeInfo riConst(r._var, r._attr, r._lowConst, r._highConst,
|
||||||
|
r.is1ValueRangeInfo());
|
||||||
|
collector[k].emplace_back(riConst);
|
||||||
|
|
||||||
|
// Now work the actual values of the variable lows and highs into
|
||||||
|
// this constant range:
|
||||||
|
for (auto l : r._lows) {
|
||||||
|
Expression* e = _allVariableBoundExpressions[posInExpressions];
|
||||||
|
TRI_ASSERT(e != nullptr);
|
||||||
|
TRI_document_collection_t const* myCollection = nullptr;
|
||||||
|
AqlValue a = e->execute(_trx, docColls, data, nrRegs * _pos,
|
||||||
|
_inVars[posInExpressions],
|
||||||
|
_inRegs[posInExpressions],
|
||||||
|
&myCollection);
|
||||||
|
posInExpressions++;
|
||||||
|
|
||||||
|
Json bound;
|
||||||
|
if (a._type == AqlValue::JSON) {
|
||||||
|
bound = *(a._json);
|
||||||
|
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);
|
||||||
|
a.destroy(); // the TRI_json_t* of a._json has been stolen
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"AQL: computed a variable bound and got non-JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! bound.isArray()) {
|
||||||
|
auto b(bound.copy());
|
||||||
|
RangeInfo ri(r._var,
|
||||||
|
r._attr,
|
||||||
|
RangeInfoBound(l.inclusive(), true, b), // will steal b's JSON
|
||||||
|
RangeInfoBound(),
|
||||||
|
false);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < collector[k].size(); j++) {
|
||||||
|
collector[k][j].fuse(ri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::vector<RangeInfo> riv;
|
||||||
|
riv.reserve(bound.size());
|
||||||
|
|
||||||
|
for (size_t j = 0; j < bound.size(); j++) {
|
||||||
|
auto b1(bound.at(static_cast<int>(j)).copy()); // first instance of bound
|
||||||
|
auto b2(bound.at(static_cast<int>(j)).copy()); // second instance of same bound
|
||||||
|
|
||||||
|
riv.emplace_back(RangeInfo(r._var,
|
||||||
|
r._attr,
|
||||||
|
RangeInfoBound(l.inclusive(), true, b1), // will steal b1's JSON
|
||||||
|
RangeInfoBound(l.inclusive(), true, b2), // will steal b2's JSON
|
||||||
|
true));
|
||||||
|
}
|
||||||
|
|
||||||
|
collector[k] = andCombineRangeInfoVecs(collector[k], riv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto h : r._highs) {
|
||||||
|
Expression* e = _allVariableBoundExpressions[posInExpressions];
|
||||||
|
TRI_ASSERT(e != nullptr);
|
||||||
|
TRI_document_collection_t const* myCollection = nullptr;
|
||||||
|
AqlValue a = e->execute(_trx, docColls, data, nrRegs * _pos,
|
||||||
|
_inVars[posInExpressions],
|
||||||
|
_inRegs[posInExpressions],
|
||||||
|
&myCollection);
|
||||||
|
posInExpressions++;
|
||||||
|
|
||||||
|
Json bound;
|
||||||
|
if (a._type == AqlValue::JSON) {
|
||||||
|
bound = *(a._json);
|
||||||
|
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);
|
||||||
|
a.destroy(); // the TRI_json_t* of a._json has been stolen
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"AQL: computed a variable bound and got non-JSON");
|
||||||
|
}
|
||||||
|
if (! bound.isArray()) {
|
||||||
|
auto b(bound.copy());
|
||||||
|
RangeInfo ri(r._var,
|
||||||
|
r._attr,
|
||||||
|
RangeInfoBound(),
|
||||||
|
RangeInfoBound(h.inclusive(), true, b), // will steal b's JSON
|
||||||
|
false);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < collector[k].size(); j++) {
|
||||||
|
collector[k][j].fuse(ri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::vector<RangeInfo> riv;
|
||||||
|
riv.reserve(bound.size());
|
||||||
|
|
||||||
|
for (size_t j = 0; j < bound.size(); j++) {
|
||||||
|
auto b1(bound.at(static_cast<int>(j)).copy()); // first instance of bound
|
||||||
|
auto b2(bound.at(static_cast<int>(j)).copy()); // second instance of same bound
|
||||||
|
|
||||||
|
riv.emplace_back(RangeInfo(r._var,
|
||||||
|
r._attr,
|
||||||
|
RangeInfoBound(h.inclusive(), true, b1), // will steal b1's JSON
|
||||||
|
RangeInfoBound(h.inclusive(), true, b2), // will steal b2's JSON
|
||||||
|
true));
|
||||||
|
}
|
||||||
|
collector[k] = andCombineRangeInfoVecs(collector[k], riv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty = false;
|
||||||
|
for (auto x: collector) {
|
||||||
|
if (x.empty()) {
|
||||||
|
isEmpty = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isEmpty) {
|
||||||
|
// otherwise the condition is impossible to fulfill
|
||||||
|
// the elements of the direct product of the collector are and
|
||||||
|
// conditions which should be added to newCondition
|
||||||
|
auto indexAnds = cartesian(collector);
|
||||||
|
|
||||||
|
if (newCondition != nullptr) {
|
||||||
|
for (auto indexAnd: *indexAnds) {
|
||||||
|
newCondition->push_back(indexAnd);
|
||||||
|
}
|
||||||
|
delete indexAnds;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newCondition = indexAnds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//_condition = newCondition.release();
|
||||||
|
if (newCondition != nullptr) {
|
||||||
|
freeCondition();
|
||||||
|
_condition = newCondition;
|
||||||
|
_freeCondition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove duplicates . . .
|
||||||
|
removeOverlapsIndexOr(*_condition);
|
||||||
|
}
|
||||||
|
|
||||||
int IndexRangeBlock::initialize () {
|
int IndexRangeBlock::initialize () {
|
||||||
ENTER_BLOCK
|
ENTER_BLOCK
|
||||||
int res = ExecutionBlock::initialize();
|
int res = ExecutionBlock::initialize();
|
||||||
|
@ -1063,6 +1249,8 @@ int IndexRangeBlock::initialize () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_allVariableBoundExpressions.clear();
|
||||||
|
|
||||||
// instanciate expressions:
|
// instanciate expressions:
|
||||||
auto instanciateExpression = [&] (RangeInfoBound& b) -> void {
|
auto instanciateExpression = [&] (RangeInfoBound& b) -> void {
|
||||||
AstNode const* a = b.getExpressionAst(_engine->getQuery()->ast());
|
AstNode const* a = b.getExpressionAst(_engine->getQuery()->ast());
|
||||||
|
@ -1078,6 +1266,7 @@ int IndexRangeBlock::initialize () {
|
||||||
delete e;
|
delete e;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare _inVars and _inRegs:
|
// Prepare _inVars and _inRegs:
|
||||||
_inVars.emplace_back();
|
_inVars.emplace_back();
|
||||||
std::vector<Variable*>& inVarsCur = _inVars.back();
|
std::vector<Variable*>& inVarsCur = _inVars.back();
|
||||||
|
@ -1123,6 +1312,8 @@ int IndexRangeBlock::initialize () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hasV8Expression = hasV8Expression();
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
LEAVE_BLOCK;
|
LEAVE_BLOCK;
|
||||||
|
@ -1147,206 +1338,43 @@ int IndexRangeBlock::initialize () {
|
||||||
bool IndexRangeBlock::initRanges () {
|
bool IndexRangeBlock::initRanges () {
|
||||||
ENTER_BLOCK
|
ENTER_BLOCK
|
||||||
_flag = true;
|
_flag = true;
|
||||||
auto en = static_cast<IndexRangeNode const*>(getPlanNode());
|
|
||||||
|
|
||||||
TRI_ASSERT(en->_index != nullptr);
|
|
||||||
|
|
||||||
// Find out about the actual values for the bounds in the variable bound case:
|
// Find out about the actual values for the bounds in the variable bound case:
|
||||||
|
|
||||||
if (_anyBoundVariable) {
|
if (_anyBoundVariable) {
|
||||||
size_t posInExpressions = 0;
|
if (_hasV8Expression) {
|
||||||
|
// must have a V8 context here to protect Expression::execute()
|
||||||
// The following are needed to evaluate expressions with local data from
|
auto engine = _engine;
|
||||||
// the current incoming item:
|
triagens::basics::ScopeGuard guard{
|
||||||
AqlItemBlock* cur = _buffer.front();
|
[&engine]() -> void {
|
||||||
vector<AqlValue>& data(cur->getData());
|
engine->getQuery()->enterContext();
|
||||||
vector<TRI_document_collection_t const*>& docColls(cur->getDocumentCollections());
|
},
|
||||||
RegisterId nrRegs = cur->getNrRegs();
|
[&]() -> void {
|
||||||
|
// must invalidate the expression now as we might be called from
|
||||||
|
// different threads
|
||||||
|
if (triagens::arango::ServerState::instance()->isRunningInCluster()) {
|
||||||
|
for (auto e : _allVariableBoundExpressions) {
|
||||||
|
e->invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine->getQuery()->exitContext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ISOLATE;
|
||||||
|
v8::HandleScope scope(isolate); // do not delete this!
|
||||||
|
|
||||||
// must have a V8 context here to protect Expression::execute()
|
buildExpressions();
|
||||||
auto engine = _engine;
|
|
||||||
triagens::basics::ScopeGuard guard{
|
|
||||||
[&engine]() -> void {
|
|
||||||
engine->getQuery()->enterContext();
|
|
||||||
},
|
|
||||||
[&]() -> void {
|
|
||||||
|
|
||||||
// must invalidate the expression now as we might be called from
|
|
||||||
// different threads
|
|
||||||
if (triagens::arango::ServerState::instance()->isRunningInCluster()) {
|
|
||||||
for (auto e : _allVariableBoundExpressions) {
|
|
||||||
e->invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
engine->getQuery()->exitContext();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ISOLATE;
|
|
||||||
v8::HandleScope scope(isolate); // do not delete this!
|
|
||||||
|
|
||||||
IndexOrCondition* newCondition = nullptr;
|
|
||||||
for (size_t i = 0; i < en->_ranges.size(); i++) {
|
|
||||||
std::vector<std::vector<RangeInfo>> collector;
|
|
||||||
//collect the evaluated bounds here
|
|
||||||
for (size_t k = 0; k < en->_ranges[i].size(); k++) {
|
|
||||||
auto r = en->_ranges[i][k];
|
|
||||||
collector.emplace_back(std::vector<RangeInfo>());
|
|
||||||
// First create a new RangeInfo containing only the constant
|
|
||||||
// low and high bound of r:
|
|
||||||
RangeInfo riConst(r._var, r._attr, r._lowConst, r._highConst,
|
|
||||||
r.is1ValueRangeInfo());
|
|
||||||
collector[k].emplace_back(riConst);
|
|
||||||
|
|
||||||
// Now work the actual values of the variable lows and highs into
|
|
||||||
// this constant range:
|
|
||||||
for (auto l : r._lows) {
|
|
||||||
Expression* e = _allVariableBoundExpressions[posInExpressions];
|
|
||||||
TRI_ASSERT(e != nullptr);
|
|
||||||
TRI_document_collection_t const* myCollection = nullptr;
|
|
||||||
AqlValue a = e->execute(_trx, docColls, data, nrRegs * _pos,
|
|
||||||
_inVars[posInExpressions],
|
|
||||||
_inRegs[posInExpressions],
|
|
||||||
&myCollection);
|
|
||||||
posInExpressions++;
|
|
||||||
|
|
||||||
Json bound;
|
|
||||||
if (a._type == AqlValue::JSON) {
|
|
||||||
bound = *(a._json);
|
|
||||||
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);
|
|
||||||
a.destroy(); // the TRI_json_t* of a._json has been stolen
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
||||||
"AQL: computed a variable bound and got non-JSON");
|
|
||||||
}
|
|
||||||
if (! bound.isArray()) {
|
|
||||||
Json json(Json::Object, 3);
|
|
||||||
json("include", Json(l.inclusive()))
|
|
||||||
("isConstant", Json(true))
|
|
||||||
("bound", bound.copy());
|
|
||||||
RangeInfo ri = RangeInfo(r._var,
|
|
||||||
r._attr,
|
|
||||||
RangeInfoBound(json),
|
|
||||||
RangeInfoBound(),
|
|
||||||
false);
|
|
||||||
for (size_t j = 0; j < collector[k].size(); j++) {
|
|
||||||
collector[k][j].fuse(ri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::vector<RangeInfo> riv;
|
|
||||||
for (size_t j = 0; j < bound.size(); j++) {
|
|
||||||
Json json(Json::Object, 3);
|
|
||||||
json("include", Json(l.inclusive()))
|
|
||||||
("isConstant", Json(true))
|
|
||||||
("bound", bound.at(static_cast<int>(j)).copy());
|
|
||||||
|
|
||||||
riv.emplace_back(RangeInfo(r._var,
|
|
||||||
r._attr,
|
|
||||||
RangeInfoBound(json),
|
|
||||||
RangeInfoBound(json),
|
|
||||||
true));
|
|
||||||
}
|
|
||||||
collector[k] = andCombineRangeInfoVecs(collector[k], riv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto h : r._highs) {
|
|
||||||
Expression* e = _allVariableBoundExpressions[posInExpressions];
|
|
||||||
TRI_ASSERT(e != nullptr);
|
|
||||||
TRI_document_collection_t const* myCollection = nullptr;
|
|
||||||
AqlValue a = e->execute(_trx, docColls, data, nrRegs * _pos,
|
|
||||||
_inVars[posInExpressions],
|
|
||||||
_inRegs[posInExpressions],
|
|
||||||
&myCollection);
|
|
||||||
posInExpressions++;
|
|
||||||
|
|
||||||
Json bound;
|
|
||||||
if (a._type == AqlValue::JSON) {
|
|
||||||
bound = *(a._json);
|
|
||||||
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);
|
|
||||||
a.destroy(); // the TRI_json_t* of a._json has been stolen
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
||||||
"AQL: computed a variable bound and got non-JSON");
|
|
||||||
}
|
|
||||||
if (! bound.isArray()) {
|
|
||||||
Json json(Json::Object, 3);
|
|
||||||
json("include", Json(h.inclusive()))
|
|
||||||
("isConstant", Json(true))
|
|
||||||
("bound", bound.copy());
|
|
||||||
RangeInfo ri = RangeInfo(r._var,
|
|
||||||
r._attr,
|
|
||||||
RangeInfoBound(),
|
|
||||||
RangeInfoBound(json),
|
|
||||||
false);
|
|
||||||
for (size_t j = 0; j < collector[k].size(); j++) {
|
|
||||||
collector[k][j].fuse(ri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::vector<RangeInfo> riv;
|
|
||||||
for (size_t j = 0; j < bound.size(); j++) {
|
|
||||||
Json json(Json::Object, 3);
|
|
||||||
json("include", Json(h.inclusive()))
|
|
||||||
("isConstant", Json(true))
|
|
||||||
("bound", bound.at(static_cast<int>(j)).copy());
|
|
||||||
|
|
||||||
riv.emplace_back(RangeInfo(r._var,
|
|
||||||
r._attr,
|
|
||||||
RangeInfoBound(json),
|
|
||||||
RangeInfoBound(json),
|
|
||||||
true));
|
|
||||||
}
|
|
||||||
collector[k] = andCombineRangeInfoVecs(collector[k], riv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEmpty = false;
|
|
||||||
for (auto x: collector) {
|
|
||||||
if (x.empty()) {
|
|
||||||
isEmpty = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! isEmpty) {
|
|
||||||
// otherwise the condition is impossible to fulfil
|
|
||||||
// the elements of the direct product of the collector are and
|
|
||||||
// conditions which should be added to newCondition
|
|
||||||
auto indexAnds = cartesian(collector);
|
|
||||||
|
|
||||||
if (newCondition != nullptr) {
|
|
||||||
for (auto indexAnd: *indexAnds) {
|
|
||||||
newCondition->push_back(indexAnd);
|
|
||||||
}
|
|
||||||
delete indexAnds;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newCondition = indexAnds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//_condition = newCondition.release();
|
else {
|
||||||
if (newCondition != nullptr) {
|
// no V8 context required!
|
||||||
freeCondition();
|
buildExpressions();
|
||||||
_condition = newCondition;
|
|
||||||
_freeCondition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove duplicates . . .
|
|
||||||
removeOverlapsIndexOr(*_condition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto en = static_cast<IndexRangeNode const*>(getPlanNode());
|
||||||
|
TRI_ASSERT(en->_index != nullptr);
|
||||||
|
|
||||||
if (en->_index->type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
if (en->_index->type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||||
return true; //no initialization here!
|
return true; //no initialization here!
|
||||||
|
|
|
@ -595,6 +595,18 @@ namespace triagens {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief whether or not one of the bounds expressions requires V8
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool hasV8Expression () const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief build the bounds expressions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void buildExpressions ();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief free _condition if it belongs to us
|
/// @brief free _condition if it belongs to us
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -829,6 +841,7 @@ namespace triagens {
|
||||||
|
|
||||||
bool _freeCondition;
|
bool _freeCondition;
|
||||||
|
|
||||||
|
bool _hasV8Expression;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -652,22 +652,29 @@ QueryResult Query::execute (QueryRegistry* registry) {
|
||||||
triagens::basics::Json jsonResult(triagens::basics::Json::Array, 16);
|
triagens::basics::Json jsonResult(triagens::basics::Json::Array, 16);
|
||||||
triagens::basics::Json stats;
|
triagens::basics::Json stats;
|
||||||
|
|
||||||
AqlItemBlock* value;
|
AqlItemBlock* value = nullptr;
|
||||||
|
|
||||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
try {
|
||||||
auto doc = value->getDocumentCollection(0);
|
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||||
size_t const n = value->size();
|
auto doc = value->getDocumentCollection(0);
|
||||||
// reserve space for n additional results at once
|
size_t const n = value->size();
|
||||||
jsonResult.reserve(n);
|
// reserve space for n additional results at once
|
||||||
|
jsonResult.reserve(n);
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
AqlValue val = value->getValue(i, 0);
|
AqlValue val = value->getValue(i, 0);
|
||||||
|
|
||||||
if (! val.isEmpty()) {
|
if (! val.isEmpty()) {
|
||||||
jsonResult.add(val.toJson(_trx, doc));
|
jsonResult.add(val.toJson(_trx, doc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
delete value;
|
||||||
|
value = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
delete value;
|
delete value;
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats = _engine->_stats.toJson();
|
stats = _engine->_stats.toJson();
|
||||||
|
@ -726,22 +733,28 @@ QueryResultV8 Query::executeV8 (v8::Isolate* isolate, QueryRegistry* registry) {
|
||||||
result.result = v8::Array::New(isolate);
|
result.result = v8::Array::New(isolate);
|
||||||
triagens::basics::Json stats;
|
triagens::basics::Json stats;
|
||||||
|
|
||||||
AqlItemBlock* value;
|
AqlItemBlock* value = nullptr;
|
||||||
|
|
||||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
try {
|
||||||
auto doc = value->getDocumentCollection(0);
|
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||||
size_t const n = value->size();
|
auto doc = value->getDocumentCollection(0);
|
||||||
// reserve space for n additional results at once
|
|
||||||
/// json.reserve(n);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
|
||||||
AqlValue val = value->getValueReference(i, 0);
|
|
||||||
|
|
||||||
if (! val.isEmpty()) {
|
size_t const n = value->size();
|
||||||
result.result->Set(j++, val.toV8(isolate, _trx, doc));
|
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
AqlValue val = value->getValueReference(i, 0);
|
||||||
|
|
||||||
|
if (! val.isEmpty()) {
|
||||||
|
result.result->Set(j++, val.toV8(isolate, _trx, doc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
delete value;
|
||||||
|
value = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
delete value;
|
delete value;
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats = _engine->_stats.toJson();
|
stats = _engine->_stats.toJson();
|
||||||
|
|
|
@ -28,11 +28,9 @@
|
||||||
#ifndef ARANGODB_AQL_RANGE_INFO_H
|
#ifndef ARANGODB_AQL_RANGE_INFO_H
|
||||||
#define ARANGODB_AQL_RANGE_INFO_H 1
|
#define ARANGODB_AQL_RANGE_INFO_H 1
|
||||||
|
|
||||||
#include <Basics/Common.h>
|
#include "Basics/Common.h"
|
||||||
#include <Basics/JsonHelper.h>
|
|
||||||
|
|
||||||
#include "Aql/AstNode.h"
|
#include "Aql/AstNode.h"
|
||||||
|
#include "Basics/JsonHelper.h"
|
||||||
#include "Basics/json-utilities.h"
|
#include "Basics/json-utilities.h"
|
||||||
|
|
||||||
namespace triagens {
|
namespace triagens {
|
||||||
|
@ -98,6 +96,21 @@ namespace triagens {
|
||||||
_defined = true;
|
_defined = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RangeInfoBound (bool include,
|
||||||
|
bool isConstant,
|
||||||
|
triagens::basics::Json& json)
|
||||||
|
: _bound(),
|
||||||
|
_include(include),
|
||||||
|
_isConstant(isConstant),
|
||||||
|
_defined(false),
|
||||||
|
_expressionAst(nullptr) {
|
||||||
|
|
||||||
|
if (! json.isEmpty()) {
|
||||||
|
_bound = triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, json.steal());
|
||||||
|
_defined = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RangeInfoBound ()
|
RangeInfoBound ()
|
||||||
: _bound(),
|
: _bound(),
|
||||||
|
|
Loading…
Reference in New Issue