diff --git a/3rdParty/iresearch/core/utils/string.hpp b/3rdParty/iresearch/core/utils/string.hpp index 8f9af819a0..e31a4f3094 100644 --- a/3rdParty/iresearch/core/utils/string.hpp +++ b/3rdParty/iresearch/core/utils/string.hpp @@ -199,8 +199,8 @@ class basic_string_ref { size_t rhs_size ) { const size_t lhs_size = lhs.size(); - int r = traits_type::compare( - lhs.c_str(), rhs, + int r = traits_type::compare( + lhs.c_str(), rhs, (std::min)(lhs_size, rhs_size) ); @@ -235,7 +235,7 @@ class basic_string_ref { ) { return lhs.compare(0, std::basic_string::npos, rhs.c_str(), rhs.size()) < 0; } - + friend bool operator>=(const basic_string_ref& lhs, const basic_string_ref& rhs) { return !(lhs < rhs); } @@ -295,7 +295,7 @@ inline bool starts_with( template< typename _Elem, typename _Traits > inline bool starts_with( - const std::basic_string<_Elem>& first, + const std::basic_string<_Elem>& first, const basic_string_ref<_Elem, _Traits>& second) { return 0 == first.compare(0, second.size(), second.c_str(), second.size()); } diff --git a/arangod/IResearch/IResearchAnalyzerFeature.cpp b/arangod/IResearch/IResearchAnalyzerFeature.cpp index 09f174b144..684ed56554 100644 --- a/arangod/IResearch/IResearchAnalyzerFeature.cpp +++ b/arangod/IResearch/IResearchAnalyzerFeature.cpp @@ -66,6 +66,8 @@ namespace { +using namespace std::literals::string_literals; + static std::string const ANALYZER_COLLECTION_NAME("_analyzers"); static char const ANALYZER_PREFIX_DELIM = ':'; // name prefix delimiter (2 chars) static size_t const ANALYZER_PROPERTIES_SIZE_MAX = 1024 * 1024; // arbitrary value @@ -132,16 +134,26 @@ bool IdentityAnalyzer::reset(irs::string_ref const& data) { return !_empty; } +static std::string const while_tokens = + " while computing result for function 'TOKENS'"; + +namespace detail { + std::string operator+(std::string const& s, irs::string_ref const& r){ + return s + std::string(r.c_str(), r.size()); + } + std::string operator+(irs::string_ref const& r, std::string const& s){ + return std::string(r.c_str(), r.size()) + s; + } +} + arangodb::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expressionContext, arangodb::transaction::Methods* trx, arangodb::aql::VPackFunctionParameters const& args) { - if (2 != args.size() || !args[0].isString() || !args[1].isString()) { - LOG_TOPIC("740fd", WARN, arangodb::iresearch::TOPIC) - << "invalid arguments passed while computing result for function " - "'TOKENS'"; - TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - return arangodb::aql::AqlValue(); + if (2 != args.size() || !args[0].isString() || !args[1].isString()) { + auto message = "invalid arguments" + while_tokens; + LOG_TOPIC("740fd", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, message); } auto data = arangodb::iresearch::getStringRef(args[0].slice()); @@ -150,12 +162,9 @@ arangodb::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expression arangodb::application_features::ApplicationServer::lookupFeature(); if (!analyzers) { - LOG_TOPIC("fbd91", WARN, arangodb::iresearch::TOPIC) - << "failure to find feature 'arangosearch' while computing result for " - "function 'TOKENS'"; - TRI_set_errno(TRI_ERROR_INTERNAL); - - return arangodb::aql::AqlValue(); + auto const message = "failure to find feature 'arangosearch'"s + while_tokens; + LOG_TOPIC("fbd91", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message); } arangodb::iresearch::IResearchAnalyzerFeature::AnalyzerPool::ptr pool; @@ -178,43 +187,40 @@ arangodb::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expression } if (!pool) { - LOG_TOPIC("0d256", WARN, arangodb::iresearch::TOPIC) - << "failure to find arangosearch analyzer pool name '" << name - << "' while computing result for function 'TOKENS'"; - TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - - return arangodb::aql::AqlValue(); + using detail::operator+; + auto const message = "failure to find arangosearch analyzer with name '"s + + name + "'" + while_tokens; + LOG_TOPIC("0d256", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, message); } auto analyzer = pool->get(); if (!analyzer) { - LOG_TOPIC("d7477", WARN, arangodb::iresearch::TOPIC) - << "failure to find arangosearch analyzer name '" << name - << "' while computing result for function 'TOKENS'"; - TRI_set_errno(TRI_ERROR_BAD_PARAMETER); - - return arangodb::aql::AqlValue(); + using detail::operator+; + auto const message = "failure to find arangosearch analyzer with name '"s + + name + "'" + while_tokens; + LOG_TOPIC("d7477", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, message); } if (!analyzer->reset(data)) { - LOG_TOPIC("45a2d", WARN, arangodb::iresearch::TOPIC) - << "failure to reset arangosearch analyzer name '" << name - << "' while computing result for function 'TOKENS'"; - TRI_set_errno(TRI_ERROR_INTERNAL); - - return arangodb::aql::AqlValue(); + using detail::operator+; + auto const message = "failure to reset arangosearch analyzer: ' "s + + name + "'" + while_tokens; + LOG_TOPIC("45a2d", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message); } auto& values = analyzer->attributes().get(); if (!values) { - LOG_TOPIC("f46f2", WARN, arangodb::iresearch::TOPIC) - << "failure to retrieve values from arangosearch analyzer name '" - << name << "' while computing result for function 'TOKENS'"; - TRI_set_errno(TRI_ERROR_INTERNAL); - - return arangodb::aql::AqlValue(); + using detail::operator+; + auto const message = + "failure to retrieve values from arangosearch analyzer name '"s + + name + "'" + while_tokens; + LOG_TOPIC("f46f2", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message); } // to avoid copying Builder's default buffer when initializing AqlValue @@ -222,11 +228,9 @@ arangodb::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expression auto buffer = irs::memory::make_unique>(); if (!buffer) { - LOG_TOPIC("97cd0", WARN, arangodb::iresearch::TOPIC) - << "failure to allocate result buffer while computing result for " - "function 'TOKENS'"; - - return arangodb::aql::AqlValue(); + auto const message = "failure to allocate result buffer"s + while_tokens; + LOG_TOPIC("97cd0", WARN, arangodb::iresearch::TOPIC) << message; + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_OUT_OF_MEMORY, message); } arangodb::velocypack::Builder builder(*buffer); diff --git a/tests/IResearch/IResearchAnalyzerFeature-test.cpp b/tests/IResearch/IResearchAnalyzerFeature-test.cpp index 335545826e..3695811279 100644 --- a/tests/IResearch/IResearchAnalyzerFeature-test.cpp +++ b/tests/IResearch/IResearchAnalyzerFeature-test.cpp @@ -2182,7 +2182,7 @@ SECTION("test_tokens") { arangodb::iresearch::IResearchAnalyzerFeature feature(s.server); // AqlFunctionFeature::byName(..) throws exception instead of returning a nullptr - CHECK_THROWS((functions->byName("TOKENS"))); + CHECK_THROWS(functions->byName("TOKENS")); feature.start(); // load AQL functions CHECK((nullptr != functions->byName("TOKENS"))); @@ -2228,8 +2228,9 @@ SECTION("test_tokens") { arangodb::SmallVector::allocator_type::arena_type arena; arangodb::aql::VPackFunctionParameters args{arena}; - AqlValueWrapper result(impl(nullptr, nullptr, args)); - CHECK((result->isNone())); + CHECK_THROWS_WITH( + AqlValueWrapper(impl(nullptr, nullptr, args)), + "invalid arguments while computing result for function 'TOKENS'"); } // test invalid data type @@ -2243,8 +2244,9 @@ SECTION("test_tokens") { VPackFunctionParametersWrapper args; args->emplace_back(data.c_str(), data.size()); args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4)); - AqlValueWrapper result(impl(nullptr, nullptr, *args)); - CHECK((result->isNone())); + CHECK_THROWS_WITH( + AqlValueWrapper(impl(nullptr, nullptr, *args)), + "invalid arguments while computing result for function 'TOKENS'"); } // test invalid analyzer type @@ -2258,8 +2260,9 @@ SECTION("test_tokens") { VPackFunctionParametersWrapper args; args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4)); args->emplace_back(analyzer.c_str(), analyzer.size()); - AqlValueWrapper result(impl(nullptr, nullptr, *args)); - CHECK((result->isNone())); + CHECK_THROWS_WITH( + AqlValueWrapper(impl(nullptr, nullptr, *args)), + "invalid arguments while computing result for function 'TOKENS'"); } // test invalid analyzer @@ -2274,8 +2277,10 @@ SECTION("test_tokens") { VPackFunctionParametersWrapper args; args->emplace_back(data.c_str(), data.size()); args->emplace_back(analyzer.c_str(), analyzer.size()); - AqlValueWrapper result(impl(nullptr, nullptr, *args)); - CHECK((result->isNone())); + CHECK_THROWS_WITH( + AqlValueWrapper(impl(nullptr, nullptr, *args)), + "failure to find arangosearch analyzer with name 'invalid' while " + "computing result for function 'TOKENS'"); } } diff --git a/tests/js/common/aql/aql-view-arangosearch-feature.js b/tests/js/common/aql/aql-view-arangosearch-feature.js index 52b11cbcb9..705b6fca47 100644 --- a/tests/js/common/aql/aql-view-arangosearch-feature.js +++ b/tests/js/common/aql/aql-view-arangosearch-feature.js @@ -207,13 +207,12 @@ function iResearchFeatureAqlTestSuite () { testDefaultAnalyzers : function() { // invalid { - let result = db._query( - "RETURN TOKENS('a quick brown fox jumps', 'invalid')", - null, - { } - ).toArray(); - assertEqual(1, result.length); - assertEqual(null, result[0]); + try { + db._query("RETURN TOKENS('a quick brown fox jumps', 'invalid')").toArray(); + fail(); + } catch (err) { + assertEqual(err.errorNum, require("internal").errors.ERROR_BAD_PARAMETER.code); + } } // text_de