1
0
Fork 0

fixes for AQL

This commit is contained in:
Jan Steemann 2016-03-11 14:54:14 +01:00
parent c814332503
commit 44070b149e
7 changed files with 73 additions and 49 deletions

View File

@ -64,7 +64,7 @@ uint64_t AqlValue::hash(arangodb::AqlTransaction* trx) const {
bool AqlValue::isNull(bool emptyIsNull) const {
AqlValueType t = type();
if (t == DOCUMENT || t == DOCVEC || t == RANGE) {
if (t == DOCVEC || t == RANGE) {
return false;
}
@ -78,7 +78,7 @@ bool AqlValue::isNull(bool emptyIsNull) const {
bool AqlValue::isNumber() const {
AqlValueType t = type();
if (t == DOCUMENT || t == DOCVEC || t == RANGE) {
if (t == DOCVEC || t == RANGE) {
return false;
}
return slice().isNumber();
@ -90,7 +90,7 @@ bool AqlValue::isNumber() const {
bool AqlValue::isString() const {
AqlValueType t = type();
if (t == DOCUMENT || t == DOCVEC || t == RANGE) {
if (t == DOCVEC || t == RANGE) {
return false;
}
return slice().isString();
@ -147,11 +147,13 @@ size_t AqlValue::length() const {
/// @brief get the (array) element at position
//////////////////////////////////////////////////////////////////////////////
AqlValue AqlValue::at(int64_t position, bool copy) const {
AqlValue AqlValue::at(int64_t position, bool& mustDestroy,
bool doCopy) const {
mustDestroy = false;
switch (type()) {
case DOCUMENT:
case VPACK_INLINE:
copy = false;
doCopy = false;
// fall-through intentional
case VPACK_EXTERNAL: {
VPackSlice s(slice());
@ -162,7 +164,8 @@ AqlValue AqlValue::at(int64_t position, bool copy) const {
position = n + position;
}
if (position >= 0 && position < n) {
if (copy || s.byteSize() < sizeof(_data.internal)) {
if (doCopy || s.byteSize() < sizeof(_data.internal)) {
mustDestroy = true;
return AqlValue(s.at(position));
}
// return a reference to an existing slice
@ -172,7 +175,6 @@ AqlValue AqlValue::at(int64_t position, bool copy) const {
// fall-through intentional
break;
}
case DOCVEC: {
size_t const n = docvecSize();
if (position < 0) {
@ -185,7 +187,8 @@ AqlValue AqlValue::at(int64_t position, bool copy) const {
for (auto const& it : *_data.docvec) {
if (position < static_cast<int64_t>(total + it->size())) {
// found the correct vector
if (copy) {
if (doCopy) {
mustDestroy = true;
return it->getValueReference(position - total, 0).clone();
}
return it->getValue(position - total, 0);
@ -207,6 +210,7 @@ AqlValue AqlValue::at(int64_t position, bool copy) const {
// only look up the value if it is within array bounds
VPackBuilder builder;
builder.add(VPackValue(_data.range->at(static_cast<size_t>(position))));
mustDestroy = true;
return AqlValue(builder);
}
// fall-through intentional
@ -223,11 +227,13 @@ AqlValue AqlValue::at(int64_t position, bool copy) const {
//////////////////////////////////////////////////////////////////////////////
AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
std::string const& name, bool copy) const {
std::string const& name, bool& mustDestroy,
bool doCopy) const {
mustDestroy = false;
switch (type()) {
case DOCUMENT:
case VPACK_INLINE:
copy = false;
doCopy = false;
// fall-through intentional
case VPACK_EXTERNAL: {
VPackSlice s(slice());
@ -238,7 +244,8 @@ AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
return AqlValue(trx->extractIdString(s));
}
if (!found.isNone()) {
if (copy || found.byteSize() < sizeof(_data.internal)) {
if (doCopy || found.byteSize() < sizeof(_data.internal)) {
mustDestroy = true;
return AqlValue(found);
}
// return a reference to an existing slice
@ -248,7 +255,6 @@ AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
// fall-through intentional
break;
}
case DOCVEC:
case RANGE: {
// will return null
@ -265,11 +271,13 @@ AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
//////////////////////////////////////////////////////////////////////////////
AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
std::vector<char const*> const& names, bool copy) const {
std::vector<char const*> const& names,
bool& mustDestroy, bool doCopy) const {
mustDestroy = false;
switch (type()) {
case DOCUMENT:
case VPACK_INLINE:
copy = false;
doCopy = false;
// fall-through intentional
case VPACK_EXTERNAL: {
VPackSlice s(slice());
@ -280,7 +288,8 @@ AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
return AqlValue(trx->extractIdString(s));
}
if (!found.isNone()) {
if (copy || found.byteSize() < sizeof(_data.internal)) {
if (doCopy || found.byteSize() < sizeof(_data.internal)) {
mustDestroy = true;
return AqlValue(found);
}
// return a reference to an existing slice
@ -290,7 +299,6 @@ AqlValue AqlValue::get(arangodb::AqlTransaction* trx,
// fall-through intentional
break;
}
case DOCVEC:
case RANGE: {
// will return null
@ -334,17 +342,18 @@ double AqlValue::toDouble(bool& failed) const {
}
else if (s.isArray()) {
if (s.length() == 1) {
return at(0, false).toDouble();
bool mustDestroy; // we can ignore destruction here
return at(0, mustDestroy, false).toDouble();
}
}
// fall-through intentional
break;
}
case DOCVEC:
case RANGE: {
if (length() == 1) {
return at(0, false).toDouble();
bool mustDestroy; // we can ignore destruction here
return at(0, mustDestroy, false).toDouble();
}
// will return 0
break;
@ -379,17 +388,19 @@ int64_t AqlValue::toInt64() const {
}
else if (s.isArray()) {
if (s.length() == 1) {
return at(0, false).toInt64();
// we can ignore destruction here
bool mustDestroy;
return at(0, mustDestroy, false).toInt64();
}
}
// fall-through intentional
break;
}
case DOCVEC:
case RANGE: {
if (length() == 1) {
return at(0, false).toInt64();
bool mustDestroy;
return at(0, mustDestroy, false).toInt64();
}
// will return 0
break;

View File

@ -221,16 +221,17 @@ struct AqlValue final {
/// @brief get the (array) element at position
//////////////////////////////////////////////////////////////////////////////
AqlValue at(int64_t position, bool copy) const;
AqlValue at(int64_t position, bool& mustDestroy, bool copy) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief get the (object) element by name(s)
//////////////////////////////////////////////////////////////////////////////
AqlValue get(arangodb::AqlTransaction* trx,
std::string const& name, bool copy) const;
std::string const& name, bool& mustDestroy, bool copy) const;
AqlValue get(arangodb::AqlTransaction* trx,
std::vector<char const*> const& names, bool copy) const;
std::vector<char const*> const& names, bool& mustDestroy,
bool copy) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief get the numeric value of an AqlValue

View File

@ -55,8 +55,7 @@ AqlValue AttributeAccessor::get(arangodb::AqlTransaction* trx,
for (auto it = vars.begin(); it != vars.end(); ++it, ++i) {
if ((*it)->id == _variable->id) {
// get the AQL value
mustDestroy = true;
return argv->getValueReference(startPos, regs[i]).get(trx, _attributeParts, true);
return argv->getValueReference(startPos, regs[i]).get(trx, _attributeParts, mustDestroy, true);
}
// fall-through intentional
}

View File

@ -49,8 +49,8 @@ class AttributeAccessor {
//////////////////////////////////////////////////////////////////////////////
AqlValue get(arangodb::AqlTransaction* trx, AqlItemBlock const*, size_t,
std::vector<Variable const*> const&,
std::vector<RegisterId> const&, bool& mustDestroy);
std::vector<Variable const*> const&,
std::vector<RegisterId> const&, bool& mustDestroy);
private:

View File

@ -250,7 +250,8 @@ AqlValue EnumerateListBlock::getAqlValue(AqlValue const& inVarReg) {
return out;
}
return inVarReg.at(_index++, true);
bool mustDestroy; // we can ignore destruction here
return inVarReg.at(_index++, mustDestroy, true);
}
void EnumerateListBlock::throwArrayExpectedException() {

View File

@ -272,7 +272,11 @@ bool Expression::findInArray(AqlValue const& left, AqlValue const& right,
// determine midpoint
size_t m = l + ((r - l) / 2);
int compareResult = AqlValue::Compare(trx, left, right.at(m, false), true);
bool localMustDestroy;
AqlValue a = right.at(m, localMustDestroy, false);
AqlValueGuard guard(a, localMustDestroy);
int compareResult = AqlValue::Compare(trx, left, a, true);
if (compareResult == 0) {
// item found in the list
@ -296,7 +300,11 @@ bool Expression::findInArray(AqlValue const& left, AqlValue const& right,
// use linear search
for (size_t i = 0; i < n; ++i) {
int compareResult = AqlValue::Compare(trx, left, right.at(i, false), false);
bool mustDestroy;
AqlValue a = right.at(i, mustDestroy, false);
AqlValueGuard guard(a, mustDestroy);
int compareResult = AqlValue::Compare(trx, left, a, false);
if (compareResult == 0) {
// item found in the list
@ -559,8 +567,7 @@ AqlValue Expression::executeSimpleExpressionAttributeAccess(
AqlValueGuard guard(result, mustDestroy);
AqlValue a = result.get(trx, name, true);
mustDestroy = true; // result may be dynamic
AqlValue a = result.get(trx, name, mustDestroy, true);
return a;
}
@ -602,8 +609,7 @@ AqlValue Expression::executeSimpleExpressionIndexedAccess(
AqlValueGuard guard(indexResult, mustDestroy);
if (indexResult.isNumber()) {
mustDestroy = true; // as we are copying
return result.at(indexResult.toInt64(), true);
return result.at(indexResult.toInt64(), mustDestroy, true);
}
if (indexResult.isString()) {
@ -612,8 +618,7 @@ AqlValue Expression::executeSimpleExpressionIndexedAccess(
try {
// stoll() might throw an exception if the string is not a number
int64_t position = static_cast<int64_t>(std::stoll(value));
mustDestroy = true; // as we are copying
return result.at(position, true);
return result.at(position, mustDestroy, true);
} catch (...) {
// no number found.
}
@ -628,14 +633,12 @@ AqlValue Expression::executeSimpleExpressionIndexedAccess(
if (indexResult.isNumber()) {
std::string const indexString = std::to_string(indexResult.toInt64());
mustDestroy = true; // as we are copying
return result.get(trx, indexString, true);
return result.get(trx, indexString, mustDestroy, true);
}
if (indexResult.isString()) {
std::string const indexString = indexResult.slice().copyString();
mustDestroy = true; // as we are copying
return result.get(trx, indexString, true);
return result.get(trx, indexString, mustDestroy, true);
}
// fall-through to returning null
@ -1054,7 +1057,10 @@ AqlValue Expression::executeSimpleExpressionArrayComparison(
size_t numLeft = n;
for (size_t i = 0; i < n; ++i) {
AqlValue leftItemValue = left.at(i, false);
bool localMustDestroy;
AqlValue leftItemValue = left.at(i, localMustDestroy, false);
AqlValueGuard guard(leftItemValue, localMustDestroy);
bool result;
// IN and NOT IN
@ -1239,7 +1245,10 @@ AqlValue Expression::executeSimpleExpressionExpansion(
size_t const n = v.length();
for (size_t i = 0; i < n; ++i) {
AqlValue item = v.at(i, false);
bool localMustDestroy;
AqlValue item = v.at(i, localMustDestroy, false);
AqlValueGuard guard(item, localMustDestroy);
bool const isArray = item.isArray();
if (!isArray || level == levels) {
@ -1247,7 +1256,6 @@ AqlValue Expression::executeSimpleExpressionExpansion(
} else if (isArray && level < levels) {
flatten(item, level + 1);
}
// item.destroy(); TODO: check if we need to destroy the item??
}
};
@ -1289,7 +1297,10 @@ AqlValue Expression::executeSimpleExpressionExpansion(
size_t const n = value.length();
for (size_t i = 0; i < n; ++i) {
AqlValue item = value.at(i, false);
bool localMustDestroy;
AqlValue item = value.at(i, localMustDestroy, false);
AqlValueGuard guard(item, localMustDestroy);
AqlValueMaterializer materializer(trx);
setVariable(variable, materializer.slice(item));
@ -1321,7 +1332,6 @@ AqlValue Expression::executeSimpleExpressionExpansion(
}
clearVariable(variable);
//item.destroy(); // TODO: do we need to destroy here?
if (takeItem && count > 0) {
// number of items to pick was restricted

View File

@ -158,10 +158,12 @@ AqlItemBlock* ModificationBlock::getSome(size_t atLeast, size_t atMost) {
int ModificationBlock::extractKey(AqlValue const& value,
std::string& key) {
if (value.isObject()) {
AqlValue sub = value.get(_trx, TRI_VOC_ATTRIBUTE_KEY, false);
bool mustDestroy;
AqlValue sub = value.get(_trx, TRI_VOC_ATTRIBUTE_KEY, mustDestroy, false);
AqlValueGuard guard(sub, mustDestroy);
if (sub.isString()) {
key.assign(sub.slice().copyString());
sub.destroy();
return TRI_ERROR_NO_ERROR;
}
} else if (value.isString()) {