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()),
|
||||
_posInRanges(0),
|
||||
_sortCoords(),
|
||||
_freeCondition(true) {
|
||||
_freeCondition(true),
|
||||
_hasV8Expression(false) {
|
||||
|
||||
auto trxCollection = _trx->trxCollection(_collection->cid());
|
||||
if (trxCollection != nullptr) {
|
||||
|
@ -1031,7 +1032,7 @@ IndexRangeBlock::IndexRangeBlock (ExecutionEngine* engine,
|
|||
isConstant &= r.isConstant();
|
||||
}
|
||||
_anyBoundVariable |= ! isConstant;
|
||||
_allBoundsConstant.push_back(isConstant);
|
||||
_allBoundsConstant.emplace_back(isConstant);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1053,6 +1054,191 @@ IndexRangeBlock::~IndexRangeBlock () {
|
|||
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 () {
|
||||
ENTER_BLOCK
|
||||
int res = ExecutionBlock::initialize();
|
||||
|
@ -1063,6 +1249,8 @@ int IndexRangeBlock::initialize () {
|
|||
}
|
||||
}
|
||||
|
||||
_allVariableBoundExpressions.clear();
|
||||
|
||||
// instanciate expressions:
|
||||
auto instanciateExpression = [&] (RangeInfoBound& b) -> void {
|
||||
AstNode const* a = b.getExpressionAst(_engine->getQuery()->ast());
|
||||
|
@ -1078,6 +1266,7 @@ int IndexRangeBlock::initialize () {
|
|||
delete e;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Prepare _inVars and _inRegs:
|
||||
_inVars.emplace_back();
|
||||
std::vector<Variable*>& inVarsCur = _inVars.back();
|
||||
|
@ -1123,6 +1312,8 @@ int IndexRangeBlock::initialize () {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
_hasV8Expression = hasV8Expression();
|
||||
|
||||
return res;
|
||||
LEAVE_BLOCK;
|
||||
|
@ -1147,206 +1338,43 @@ int IndexRangeBlock::initialize () {
|
|||
bool IndexRangeBlock::initRanges () {
|
||||
ENTER_BLOCK
|
||||
_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:
|
||||
|
||||
if (_anyBoundVariable) {
|
||||
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();
|
||||
if (_hasV8Expression) {
|
||||
// must have a V8 context here to protect Expression::execute()
|
||||
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!
|
||||
|
||||
// must have a V8 context here to protect Expression::execute()
|
||||
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;
|
||||
}
|
||||
}
|
||||
buildExpressions();
|
||||
}
|
||||
//_condition = newCondition.release();
|
||||
if (newCondition != nullptr) {
|
||||
freeCondition();
|
||||
_condition = newCondition;
|
||||
_freeCondition = true;
|
||||
else {
|
||||
// no V8 context required!
|
||||
buildExpressions();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return true; //no initialization here!
|
||||
|
|
|
@ -595,6 +595,18 @@ namespace triagens {
|
|||
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -829,6 +841,7 @@ namespace triagens {
|
|||
|
||||
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 stats;
|
||||
|
||||
AqlItemBlock* value;
|
||||
AqlItemBlock* value = nullptr;
|
||||
|
||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||
auto doc = value->getDocumentCollection(0);
|
||||
size_t const n = value->size();
|
||||
// reserve space for n additional results at once
|
||||
jsonResult.reserve(n);
|
||||
try {
|
||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||
auto doc = value->getDocumentCollection(0);
|
||||
size_t const n = value->size();
|
||||
// reserve space for n additional results at once
|
||||
jsonResult.reserve(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue val = value->getValue(i, 0);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue val = value->getValue(i, 0);
|
||||
|
||||
if (! val.isEmpty()) {
|
||||
jsonResult.add(val.toJson(_trx, doc));
|
||||
if (! val.isEmpty()) {
|
||||
jsonResult.add(val.toJson(_trx, doc));
|
||||
}
|
||||
}
|
||||
delete value;
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
delete value;
|
||||
throw;
|
||||
}
|
||||
|
||||
stats = _engine->_stats.toJson();
|
||||
|
@ -726,22 +733,28 @@ QueryResultV8 Query::executeV8 (v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
result.result = v8::Array::New(isolate);
|
||||
triagens::basics::Json stats;
|
||||
|
||||
AqlItemBlock* value;
|
||||
AqlItemBlock* value = nullptr;
|
||||
|
||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||
auto doc = value->getDocumentCollection(0);
|
||||
size_t const n = value->size();
|
||||
// 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);
|
||||
try {
|
||||
while (nullptr != (value = _engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
|
||||
auto doc = value->getDocumentCollection(0);
|
||||
|
||||
if (! val.isEmpty()) {
|
||||
result.result->Set(j++, val.toV8(isolate, _trx, doc));
|
||||
size_t const n = value->size();
|
||||
|
||||
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;
|
||||
throw;
|
||||
}
|
||||
|
||||
stats = _engine->_stats.toJson();
|
||||
|
|
|
@ -28,11 +28,9 @@
|
|||
#ifndef ARANGODB_AQL_RANGE_INFO_H
|
||||
#define ARANGODB_AQL_RANGE_INFO_H 1
|
||||
|
||||
#include <Basics/Common.h>
|
||||
#include <Basics/JsonHelper.h>
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/AstNode.h"
|
||||
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "Basics/json-utilities.h"
|
||||
|
||||
namespace triagens {
|
||||
|
@ -98,6 +96,21 @@ namespace triagens {
|
|||
_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 ()
|
||||
: _bound(),
|
||||
|
|
Loading…
Reference in New Issue