1
0
Fork 0

improve error messages if FOR doesn't find proper values to work with

This commit is contained in:
Wilfried Goesgens 2017-01-10 13:17:04 +01:00
parent 150ff8a1e3
commit 8c39c975a4
5 changed files with 48 additions and 6 deletions

View File

@ -155,6 +155,35 @@ bool AqlValue::isArray() const noexcept {
}
}
std::array<std::string const, 8> AqlValue::typeStrings = {
"none",
"null",
"bool",
"number",
"string",
"object",
"array",
"unknown"};
std::string const & AqlValue::getTypeString() const noexcept {
if(isNone()) {
return typeStrings[0];
} else if(isNull(true)) {
return typeStrings[1];
} else if(isBoolean()) {
return typeStrings[2];
} else if(isNumber()) {
return typeStrings[3];
} else if(isString()) {
return typeStrings[4];
} else if(isObject()) {
return typeStrings[5];
} else if(isArray()){
return typeStrings[6];
}
return typeStrings[7];
}
/// @brief get the (array) length (note: this treats ranges as arrays, too!)
size_t AqlValue::length() const {
switch (type()) {

View File

@ -83,6 +83,7 @@ struct AqlValueFromManagedDocument {};
struct AqlValue final {
friend struct std::hash<arangodb::aql::AqlValue>;
friend struct std::equal_to<arangodb::aql::AqlValue>;
static std::array<std::string const, 8> typeStrings;
public:
@ -388,6 +389,10 @@ struct AqlValue final {
/// @brief whether or not the value is an array (note: this treats ranges
/// as arrays, too!)
bool isArray() const noexcept;
// @brief return a string describing the content of this aqlvalue
std::string const & getTypeString() const noexcept;
/// @brief get the (array) length (note: this treats ranges as arrays, too!)
size_t length() const;

View File

@ -2889,8 +2889,13 @@ AstNode* Ast::optimizeFor(AstNode* node) {
// right-hand operand to FOR statement is no array
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_QUERY_ARRAY_EXPECTED,
std::string("collection or ") +
TRI_errno_string(TRI_ERROR_QUERY_ARRAY_EXPECTED) +
std::string(" as operand to FOR loop"));
std::string(" as operand to FOR loop; you specified type '") +
expression->getValueTypeString() +
std::string("' with content '") +
expression->toString() +
std::string("'"));
}
// no real optimizations will be done here

View File

@ -98,7 +98,7 @@ AqlItemBlock* EnumerateListBlock::getSome(size_t, size_t atMost) {
AqlValue const& inVarReg = cur->getValueReference(_pos, _inVarRegId);
if (!inVarReg.isArray()) {
throwArrayExpectedException();
throwArrayExpectedException(inVarReg);
}
size_t sizeInVar;
@ -195,7 +195,7 @@ size_t EnumerateListBlock::skipSome(size_t atLeast, size_t atMost) {
AqlValue const& inVarReg = cur->getValueReference(_pos, _inVarRegId);
// get the size of the thing we are looping over
if (!inVarReg.isArray()) {
throwArrayExpectedException();
throwArrayExpectedException(inVarReg);
}
size_t sizeInVar;
@ -253,9 +253,12 @@ AqlValue EnumerateListBlock::getAqlValue(AqlValue const& inVarReg, bool& mustDes
DEBUG_END_BLOCK();
}
void EnumerateListBlock::throwArrayExpectedException() {
void EnumerateListBlock::throwArrayExpectedException(AqlValue const& value) {
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_QUERY_ARRAY_EXPECTED,
std::string("collection or ") +
TRI_errno_string(TRI_ERROR_QUERY_ARRAY_EXPECTED) +
std::string(" as operand to FOR loop"));
std::string(" as operand to FOR loop; you provided a value of type '") +
value.getTypeString () +
std::string("'"));
}

View File

@ -54,7 +54,7 @@ class EnumerateListBlock : public ExecutionBlock {
AqlValue getAqlValue(AqlValue const&, bool& mustDestroy);
// cppcheck-suppress *
void throwArrayExpectedException();
void throwArrayExpectedException(AqlValue const& value);
private:
// current position in the _inVariable