1
0
Fork 0

add exceptions for tokens function. (#8984)

* Provide users of the TOKENS function with errors.

* remove newlines

* fix compare

* fix as asked for

* improve fix
This commit is contained in:
Jan Christoph Uhde 2019-05-16 21:12:43 +02:00 committed by Andrey Abramov
parent 145cf3d294
commit 970f732dec
4 changed files with 69 additions and 61 deletions

View File

@ -199,8 +199,8 @@ class basic_string_ref {
size_t rhs_size size_t rhs_size
) { ) {
const size_t lhs_size = lhs.size(); const size_t lhs_size = lhs.size();
int r = traits_type::compare( int r = traits_type::compare(
lhs.c_str(), rhs, lhs.c_str(), rhs,
(std::min)(lhs_size, rhs_size) (std::min)(lhs_size, rhs_size)
); );
@ -235,7 +235,7 @@ class basic_string_ref {
) { ) {
return lhs.compare(0, std::basic_string<char_type>::npos, rhs.c_str(), rhs.size()) < 0; return lhs.compare(0, std::basic_string<char_type>::npos, rhs.c_str(), rhs.size()) < 0;
} }
friend bool operator>=(const basic_string_ref& lhs, const basic_string_ref& rhs) { friend bool operator>=(const basic_string_ref& lhs, const basic_string_ref& rhs) {
return !(lhs < rhs); return !(lhs < rhs);
} }
@ -295,7 +295,7 @@ inline bool starts_with(
template< typename _Elem, typename _Traits > template< typename _Elem, typename _Traits >
inline bool starts_with( inline bool starts_with(
const std::basic_string<_Elem>& first, const std::basic_string<_Elem>& first,
const basic_string_ref<_Elem, _Traits>& second) { const basic_string_ref<_Elem, _Traits>& second) {
return 0 == first.compare(0, second.size(), second.c_str(), second.size()); return 0 == first.compare(0, second.size(), second.c_str(), second.size());
} }

View File

@ -66,6 +66,8 @@
namespace { namespace {
using namespace std::literals::string_literals;
static std::string const ANALYZER_COLLECTION_NAME("_analyzers"); static std::string const ANALYZER_COLLECTION_NAME("_analyzers");
static char const ANALYZER_PREFIX_DELIM = ':'; // name prefix delimiter (2 chars) static char const ANALYZER_PREFIX_DELIM = ':'; // name prefix delimiter (2 chars)
static size_t const ANALYZER_PROPERTIES_SIZE_MAX = 1024 * 1024; // arbitrary value 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; 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::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expressionContext,
arangodb::transaction::Methods* trx, arangodb::transaction::Methods* trx,
arangodb::aql::VPackFunctionParameters const& args) { 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()); 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<arangodb::iresearch::IResearchAnalyzerFeature>(); arangodb::application_features::ApplicationServer::lookupFeature<arangodb::iresearch::IResearchAnalyzerFeature>();
if (!analyzers) { if (!analyzers) {
LOG_TOPIC("fbd91", WARN, arangodb::iresearch::TOPIC) auto const message = "failure to find feature 'arangosearch'"s + while_tokens;
<< "failure to find feature 'arangosearch' while computing result for " LOG_TOPIC("fbd91", WARN, arangodb::iresearch::TOPIC) << message;
"function 'TOKENS'"; THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message);
TRI_set_errno(TRI_ERROR_INTERNAL);
return arangodb::aql::AqlValue();
} }
arangodb::iresearch::IResearchAnalyzerFeature::AnalyzerPool::ptr pool; arangodb::iresearch::IResearchAnalyzerFeature::AnalyzerPool::ptr pool;
@ -178,43 +187,40 @@ arangodb::aql::AqlValue aqlFnTokens(arangodb::aql::ExpressionContext* expression
} }
if (!pool) { if (!pool) {
LOG_TOPIC("0d256", WARN, arangodb::iresearch::TOPIC) using detail::operator+;
<< "failure to find arangosearch analyzer pool name '" << name auto const message = "failure to find arangosearch analyzer with name '"s +
<< "' while computing result for function 'TOKENS'"; name + "'" + while_tokens;
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); LOG_TOPIC("0d256", WARN, arangodb::iresearch::TOPIC) << message;
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, message);
return arangodb::aql::AqlValue();
} }
auto analyzer = pool->get(); auto analyzer = pool->get();
if (!analyzer) { if (!analyzer) {
LOG_TOPIC("d7477", WARN, arangodb::iresearch::TOPIC) using detail::operator+;
<< "failure to find arangosearch analyzer name '" << name auto const message = "failure to find arangosearch analyzer with name '"s +
<< "' while computing result for function 'TOKENS'"; name + "'" + while_tokens;
TRI_set_errno(TRI_ERROR_BAD_PARAMETER); LOG_TOPIC("d7477", WARN, arangodb::iresearch::TOPIC) << message;
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, message);
return arangodb::aql::AqlValue();
} }
if (!analyzer->reset(data)) { if (!analyzer->reset(data)) {
LOG_TOPIC("45a2d", WARN, arangodb::iresearch::TOPIC) using detail::operator+;
<< "failure to reset arangosearch analyzer name '" << name auto const message = "failure to reset arangosearch analyzer: ' "s +
<< "' while computing result for function 'TOKENS'"; name + "'" + while_tokens;
TRI_set_errno(TRI_ERROR_INTERNAL); LOG_TOPIC("45a2d", WARN, arangodb::iresearch::TOPIC) << message;
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message);
return arangodb::aql::AqlValue();
} }
auto& values = analyzer->attributes().get<irs::term_attribute>(); auto& values = analyzer->attributes().get<irs::term_attribute>();
if (!values) { if (!values) {
LOG_TOPIC("f46f2", WARN, arangodb::iresearch::TOPIC) using detail::operator+;
<< "failure to retrieve values from arangosearch analyzer name '" auto const message =
<< name << "' while computing result for function 'TOKENS'"; "failure to retrieve values from arangosearch analyzer name '"s +
TRI_set_errno(TRI_ERROR_INTERNAL); name + "'" + while_tokens;
LOG_TOPIC("f46f2", WARN, arangodb::iresearch::TOPIC) << message;
return arangodb::aql::AqlValue(); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, message);
} }
// to avoid copying Builder's default buffer when initializing AqlValue // 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<arangodb::velocypack::Buffer<uint8_t>>(); auto buffer = irs::memory::make_unique<arangodb::velocypack::Buffer<uint8_t>>();
if (!buffer) { if (!buffer) {
LOG_TOPIC("97cd0", WARN, arangodb::iresearch::TOPIC) auto const message = "failure to allocate result buffer"s + while_tokens;
<< "failure to allocate result buffer while computing result for " LOG_TOPIC("97cd0", WARN, arangodb::iresearch::TOPIC) << message;
"function 'TOKENS'"; THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_OUT_OF_MEMORY, message);
return arangodb::aql::AqlValue();
} }
arangodb::velocypack::Builder builder(*buffer); arangodb::velocypack::Builder builder(*buffer);

View File

@ -2182,7 +2182,7 @@ SECTION("test_tokens") {
arangodb::iresearch::IResearchAnalyzerFeature feature(s.server); arangodb::iresearch::IResearchAnalyzerFeature feature(s.server);
// AqlFunctionFeature::byName(..) throws exception instead of returning a nullptr // AqlFunctionFeature::byName(..) throws exception instead of returning a nullptr
CHECK_THROWS((functions->byName("TOKENS"))); CHECK_THROWS(functions->byName("TOKENS"));
feature.start(); // load AQL functions feature.start(); // load AQL functions
CHECK((nullptr != functions->byName("TOKENS"))); CHECK((nullptr != functions->byName("TOKENS")));
@ -2228,8 +2228,9 @@ SECTION("test_tokens") {
arangodb::SmallVector<arangodb::aql::AqlValue>::allocator_type::arena_type arena; arangodb::SmallVector<arangodb::aql::AqlValue>::allocator_type::arena_type arena;
arangodb::aql::VPackFunctionParameters args{arena}; arangodb::aql::VPackFunctionParameters args{arena};
AqlValueWrapper result(impl(nullptr, nullptr, args)); CHECK_THROWS_WITH(
CHECK((result->isNone())); AqlValueWrapper(impl(nullptr, nullptr, args)),
"invalid arguments while computing result for function 'TOKENS'");
} }
// test invalid data type // test invalid data type
@ -2243,8 +2244,9 @@ SECTION("test_tokens") {
VPackFunctionParametersWrapper args; VPackFunctionParametersWrapper args;
args->emplace_back(data.c_str(), data.size()); args->emplace_back(data.c_str(), data.size());
args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4)); args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4));
AqlValueWrapper result(impl(nullptr, nullptr, *args)); CHECK_THROWS_WITH(
CHECK((result->isNone())); AqlValueWrapper(impl(nullptr, nullptr, *args)),
"invalid arguments while computing result for function 'TOKENS'");
} }
// test invalid analyzer type // test invalid analyzer type
@ -2258,8 +2260,9 @@ SECTION("test_tokens") {
VPackFunctionParametersWrapper args; VPackFunctionParametersWrapper args;
args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4)); args->emplace_back(arangodb::aql::AqlValueHintDouble(123.4));
args->emplace_back(analyzer.c_str(), analyzer.size()); args->emplace_back(analyzer.c_str(), analyzer.size());
AqlValueWrapper result(impl(nullptr, nullptr, *args)); CHECK_THROWS_WITH(
CHECK((result->isNone())); AqlValueWrapper(impl(nullptr, nullptr, *args)),
"invalid arguments while computing result for function 'TOKENS'");
} }
// test invalid analyzer // test invalid analyzer
@ -2274,8 +2277,10 @@ SECTION("test_tokens") {
VPackFunctionParametersWrapper args; VPackFunctionParametersWrapper args;
args->emplace_back(data.c_str(), data.size()); args->emplace_back(data.c_str(), data.size());
args->emplace_back(analyzer.c_str(), analyzer.size()); args->emplace_back(analyzer.c_str(), analyzer.size());
AqlValueWrapper result(impl(nullptr, nullptr, *args)); CHECK_THROWS_WITH(
CHECK((result->isNone())); AqlValueWrapper(impl(nullptr, nullptr, *args)),
"failure to find arangosearch analyzer with name 'invalid' while "
"computing result for function 'TOKENS'");
} }
} }

View File

@ -207,13 +207,12 @@ function iResearchFeatureAqlTestSuite () {
testDefaultAnalyzers : function() { testDefaultAnalyzers : function() {
// invalid // invalid
{ {
let result = db._query( try {
"RETURN TOKENS('a quick brown fox jumps', 'invalid')", db._query("RETURN TOKENS('a quick brown fox jumps', 'invalid')").toArray();
null, fail();
{ } } catch (err) {
).toArray(); assertEqual(err.errorNum, require("internal").errors.ERROR_BAD_PARAMETER.code);
assertEqual(1, result.length); }
assertEqual(null, result[0]);
} }
// text_de // text_de