diff --git a/CHANGELOG b/CHANGELOG index 616ca8bdf1..7bb5fd7589 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ v3.5.2 (XXXX-XX-XX) ------------------- +* Fixed issue #10270: Query: Expecting type Array or Object (while executing). + * Fix a problem with AQL constrained sort in the cluster, which might abort queries. The AQL sort-limit optimization rule may now also speed up fullCount with sorted indexes and a limit in the cluster. @@ -9,8 +11,8 @@ v3.5.2 (XXXX-XX-XX) x s" from occurring when this is not the case. Due to a data race, the message could previously also occur if the queue was empty. -* The General Graph document API is now persistent with the document API in its - errormessages. When attempting to create / modify edges pointing to non +* The General Graph document API is now consistent with the document API in its + error messages. When attempting to create / modify edges pointing to non existing vertex collections HTTP 400 is returned instead of 404. * Disallow the usage of subqueries inside AQL traversal PRUNE conditions. diff --git a/arangod/Aql/EnumerateListExecutor.cpp b/arangod/Aql/EnumerateListExecutor.cpp index f4a564dd1d..fa36332287 100644 --- a/arangod/Aql/EnumerateListExecutor.cpp +++ b/arangod/Aql/EnumerateListExecutor.cpp @@ -38,6 +38,17 @@ using namespace arangodb; using namespace arangodb::aql; +namespace { +void 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; you provided a value of type '") + + value.getTypeString() + std::string("'")); +} +} // namespace + EnumerateListExecutorInfos::EnumerateListExecutorInfos( RegisterId inputRegister, RegisterId outputRegister, RegisterId nrInputRegisters, RegisterId nrOutputRegisters, @@ -65,7 +76,6 @@ std::pair EnumerateListExecutor::produceRows(OutputAqlI // HIT in first run, because pos and length are initiliazed // both with 0 - // if (_inputArrayPosition == _inputArrayLength || _inputArrayPosition == _inputArrayLength - 1) { if (_inputArrayPosition == _inputArrayLength) { // we need to set position back to zero // because we finished iterating over existing array @@ -94,6 +104,9 @@ std::pair EnumerateListExecutor::produceRows(OutputAqlI if (inputList.isDocvec()) { _inputArrayLength = inputList.docvecSize(); } else { + if (!inputList.isArray()) { + throwArrayExpectedException(inputList); + } _inputArrayLength = inputList.length(); } } diff --git a/tests/js/server/aql/aql-queries-simple.js b/tests/js/server/aql/aql-queries-simple.js index 7c2f674467..e697074771 100644 --- a/tests/js/server/aql/aql-queries-simple.js +++ b/tests/js/server/aql/aql-queries-simple.js @@ -41,20 +41,6 @@ var assertQueryError = helper.assertQueryError; function ahuacatlQuerySimpleTestSuite () { return { -//////////////////////////////////////////////////////////////////////////////// -/// @brief set up -//////////////////////////////////////////////////////////////////////////////// - - setUp : function () { - }, - -//////////////////////////////////////////////////////////////////////////////// -/// @brief tear down -//////////////////////////////////////////////////////////////////////////////// - - tearDown : function () { - }, - testNoArraySorting1 : function () { let query = "LET values = [9,16,8,15,7,14,6,13,5,12,4,11,3,10,2,1] RETURN values"; assertEqual([9, 16, 8, 15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 1], AQL_EXECUTE(query).json[0]); @@ -1338,7 +1324,13 @@ function ahuacatlQuerySimpleTestSuite () { var actual = getQueryResults(query[0]); assertEqual(query[1], actual); }); - } + }, + + testForWithoutArray : function () { + assertQueryError(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "LET a = null FOR x IN a RETURN 1"); + + assertQueryError(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "LET a = NOOPT(null) FOR x IN a RETURN 1"); + }, }; }