mirror of https://gitee.com/bigwinds/arangodb
locally tested only (#4476)
This commit is contained in:
parent
28e645af2a
commit
aa041ddfb9
|
@ -138,10 +138,18 @@ if (USE_IRESEARCH)
|
|||
set(ICU_FOUND TRUE) # ICU built from source in 3rdParty directory
|
||||
endif()
|
||||
|
||||
if(NOT PERL_FOUND)
|
||||
set(PERL_FOUND TRUE) # suppress error for Perl not-found
|
||||
|
||||
# MSVC will execute ADD_CUSTOM_COMMAND even though OUTPUT is already present
|
||||
if(MSVC)
|
||||
set(PERL_EXECUTABLE echo)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LZ4_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/lz4")
|
||||
set(SNOWBALL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/snowball")
|
||||
set(UNWIND_ROOT "invalid")
|
||||
set(USE_IQL OFF CACHE BOOL "Use IQL" FORCE) # skip IQL
|
||||
|
||||
set(IRESEARCH_EXCLUDE_STATIC_THIRD_PARTY_LIBS TRUE) # disable linking in of 3rd party libraries automatically
|
||||
find_package(IResearch REQUIRED) # set IRESEARCH_BUILD_DIR
|
||||
|
@ -151,6 +159,8 @@ if (USE_IRESEARCH)
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake" # cmake overrides (must be first)
|
||||
"${IRESEARCH_ROOT}/cmake" # to find iResearch dependencies
|
||||
)
|
||||
|
||||
file(COPY "${IRESEARCH_ROOT}.build/" DESTINATION "${IRESEARCH_BUILD_DIR}" FILES_MATCHING PATTERN "*")
|
||||
add_subdirectory("${IRESEARCH_ROOT}" "${IRESEARCH_BUILD_DIR}" EXCLUDE_FROM_ALL) # do not build unused targets
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH_ORIGINAL}) # restore CMAKE_MODULE_PATH
|
||||
unset(BUILD_SHARED_LIBS) # otherwise ZLib (below) does not build on win32
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Locations for Bison parsers in C++
|
||||
|
||||
// Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// As a special exception, you may create a larger work that contains
|
||||
// part or all of the Bison parser skeleton and distribute that work
|
||||
// under terms of your choice, so long as that work isn't itself a
|
||||
// parser generator using the skeleton or a modified version thereof
|
||||
// as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
// the parser skeleton itself, you may (at your option) remove this
|
||||
// special exception, which will cause the skeleton and the resulting
|
||||
// Bison output files to be licensed under the GNU General Public
|
||||
// License without this special exception.
|
||||
|
||||
// This special exception was added by the Free Software Foundation in
|
||||
// version 2.2 of Bison.
|
||||
|
||||
/**
|
||||
** \file location.hh
|
||||
** Define the iresearch::iql::location class.
|
||||
*/
|
||||
|
||||
#ifndef YY_YY_LOCATION_HH_INCLUDED
|
||||
# define YY_YY_LOCATION_HH_INCLUDED
|
||||
|
||||
# include "position.hh"
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // location.cc:296
|
||||
namespace iresearch { namespace iql {
|
||||
#line 46 "location.hh" // location.cc:296
|
||||
/// Abstract a location.
|
||||
class location
|
||||
{
|
||||
public:
|
||||
|
||||
/// Initialization.
|
||||
void initialize (std::string* f = YY_NULLPTR,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
{
|
||||
begin.initialize (f, l, c);
|
||||
end = begin;
|
||||
}
|
||||
|
||||
/** \name Line and Column related manipulators
|
||||
** \{ */
|
||||
public:
|
||||
/// Reset initial location to final location.
|
||||
void step ()
|
||||
{
|
||||
begin = end;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next columns.
|
||||
void columns (int count = 1)
|
||||
{
|
||||
end += count;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next lines.
|
||||
void lines (int count = 1)
|
||||
{
|
||||
end.lines (count);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
|
||||
public:
|
||||
/// Beginning of the located region.
|
||||
position begin;
|
||||
/// End of the located region.
|
||||
position end;
|
||||
};
|
||||
|
||||
/// Join two locations, in place.
|
||||
inline location& operator+= (location& res, const location& end)
|
||||
{
|
||||
res.end = end.end;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Join two locations.
|
||||
inline location operator+ (location res, const location& end)
|
||||
{
|
||||
return res += end;
|
||||
}
|
||||
|
||||
/// Add \a width columns to the end position, in place.
|
||||
inline location& operator+= (location& res, int width)
|
||||
{
|
||||
res.columns (width);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Add \a width columns to the end position.
|
||||
inline location operator+ (location res, int width)
|
||||
{
|
||||
return res += width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns to the end position, in place.
|
||||
inline location& operator-= (location& res, int width)
|
||||
{
|
||||
return res += -width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns to the end position.
|
||||
inline location operator- (location res, int width)
|
||||
{
|
||||
return res -= width;
|
||||
}
|
||||
|
||||
/// Compare two location objects.
|
||||
inline bool
|
||||
operator== (const location& loc1, const location& loc2)
|
||||
{
|
||||
return loc1.begin == loc2.begin && loc1.end == loc2.end;
|
||||
}
|
||||
|
||||
/// Compare two location objects.
|
||||
inline bool
|
||||
operator!= (const location& loc1, const location& loc2)
|
||||
{
|
||||
return !(loc1 == loc2);
|
||||
}
|
||||
|
||||
/** \brief Intercept output stream redirection.
|
||||
** \param ostr the destination output stream
|
||||
** \param loc a reference to the location to redirect
|
||||
**
|
||||
** Avoid duplicate information.
|
||||
*/
|
||||
template <typename YYChar>
|
||||
inline std::basic_ostream<YYChar>&
|
||||
operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
|
||||
{
|
||||
unsigned int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
|
||||
ostr << loc.begin;
|
||||
if (loc.end.filename
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *loc.end.filename))
|
||||
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
|
||||
else if (loc.begin.line < loc.end.line)
|
||||
ostr << '-' << loc.end.line << '.' << end_col;
|
||||
else if (loc.begin.column < end_col)
|
||||
ostr << '-' << end_col;
|
||||
return ostr;
|
||||
}
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // location.cc:296
|
||||
} } // iresearch::iql
|
||||
#line 168 "location.hh" // location.cc:296
|
||||
#endif // !YY_YY_LOCATION_HH_INCLUDED
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,379 @@
|
|||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Skeleton interface for Bison GLR parsers in C++
|
||||
|
||||
// Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// As a special exception, you may create a larger work that contains
|
||||
// part or all of the Bison parser skeleton and distribute that work
|
||||
// under terms of your choice, so long as that work isn't itself a
|
||||
// parser generator using the skeleton or a modified version thereof
|
||||
// as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
// the parser skeleton itself, you may (at your option) remove this
|
||||
// special exception, which will cause the skeleton and the resulting
|
||||
// Bison output files to be licensed under the GNU General Public
|
||||
// License without this special exception.
|
||||
|
||||
// This special exception was added by the Free Software Foundation in
|
||||
// version 2.2 of Bison.
|
||||
|
||||
// C++ GLR parser skeleton written by Akim Demaille.
|
||||
|
||||
#ifndef YY_YY_PARSER_HH_INCLUDED
|
||||
# define YY_YY_PARSER_HH_INCLUDED
|
||||
// // "%code requires" blocks.
|
||||
#line 39 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // glr.cc:329
|
||||
|
||||
#define YYSTYPE size_t
|
||||
|
||||
#if YYDEBUG
|
||||
#define YYERROR_VERBOSE 1
|
||||
|
||||
// this is required only for %skeleton "glr.cc" since it lacks default init
|
||||
// not needed for %skeleton "lalr1.cc" or without %skeleton
|
||||
#define YYLTYPE iresearch::iql::location_type1
|
||||
#endif
|
||||
|
||||
namespace iresearch {
|
||||
namespace iql {
|
||||
class context;
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress warnings due to Bison generated code (push section, pop just below)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4512)
|
||||
#endif
|
||||
|
||||
// ALWAYS!!! define YYDEBUG 1 for the length of the header so as to avoid
|
||||
// alignment issues when linkning without YYDEBUG agains a library that was
|
||||
// built with YYDEBUG or vice versa, reverse at end of header
|
||||
#undef YYDEBUG_REQUESTED
|
||||
#if YYDEBUG
|
||||
#define YYDEBUG_REQUESTED
|
||||
#else
|
||||
#undef YYDEBUG
|
||||
#define YYDEBUG 1
|
||||
#endif
|
||||
|
||||
#line 73 "parser.hh" // glr.cc:329
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "location.hh"
|
||||
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // glr.cc:329
|
||||
namespace iresearch { namespace iql {
|
||||
#line 88 "parser.hh" // glr.cc:329
|
||||
|
||||
|
||||
/// A Bison parser.
|
||||
class parser
|
||||
{
|
||||
public:
|
||||
#ifndef YYSTYPE
|
||||
/// Symbol semantic values.
|
||||
typedef int semantic_type;
|
||||
#else
|
||||
typedef YYSTYPE semantic_type;
|
||||
#endif
|
||||
/// Symbol locations.
|
||||
typedef location location_type;
|
||||
|
||||
/// Syntax errors thrown from user actions.
|
||||
struct syntax_error : std::runtime_error
|
||||
{
|
||||
syntax_error (const location_type& l, const std::string& m);
|
||||
location_type location;
|
||||
};
|
||||
|
||||
/// Tokens.
|
||||
struct token
|
||||
{
|
||||
enum yytokentype
|
||||
{
|
||||
IQL_EOF = 0,
|
||||
IQL_UNKNOWN = 258,
|
||||
IQL_SEP = 259,
|
||||
IQL_SEQUENCE = 260,
|
||||
IQL_NOT = 261,
|
||||
IQL_EXCLAIM = 262,
|
||||
IQL_AND = 263,
|
||||
IQL_AMPAMP = 264,
|
||||
IQL_OR = 265,
|
||||
IQL_PIPEPIPE = 266,
|
||||
IQL_NE = 267,
|
||||
IQL_LE = 268,
|
||||
IQL_EQ = 269,
|
||||
IQL_GE = 270,
|
||||
IQL_LIKE = 271,
|
||||
IQL_ASTERISK = 272,
|
||||
IQL_ASC = 273,
|
||||
IQL_DESC = 274,
|
||||
IQL_COMMA = 275,
|
||||
IQL_SQUOTE = 276,
|
||||
IQL_DQUOTE = 277,
|
||||
IQL_LCHEVRON = 278,
|
||||
IQL_RCHEVRON = 279,
|
||||
IQL_LPAREN = 280,
|
||||
IQL_RPAREN = 281,
|
||||
IQL_LSBRACKET = 282,
|
||||
IQL_RSBRACKET = 283,
|
||||
IQL_LIMIT = 284,
|
||||
IQL_ORDER = 285
|
||||
};
|
||||
};
|
||||
|
||||
/// (External) token type, as returned by yylex.
|
||||
typedef token::yytokentype token_type;
|
||||
|
||||
/// Symbol type: an internal symbol number.
|
||||
typedef int symbol_number_type;
|
||||
|
||||
/// The symbol type number to denote an empty symbol.
|
||||
enum { empty_symbol = -2 };
|
||||
|
||||
/// Internal symbol number for tokens (subsumed by symbol_number_type).
|
||||
typedef unsigned char token_number_type;
|
||||
|
||||
/// A complete symbol.
|
||||
///
|
||||
/// Expects its Base type to provide access to the symbol type
|
||||
/// via type_get().
|
||||
///
|
||||
/// Provide access to semantic value and location.
|
||||
template <typename Base>
|
||||
struct basic_symbol : Base
|
||||
{
|
||||
/// Alias to Base.
|
||||
typedef Base super_type;
|
||||
|
||||
/// Default constructor.
|
||||
basic_symbol ();
|
||||
|
||||
/// Copy constructor.
|
||||
basic_symbol (const basic_symbol& other);
|
||||
|
||||
/// Constructor for valueless symbols.
|
||||
basic_symbol (typename Base::kind_type t,
|
||||
const location_type& l);
|
||||
|
||||
/// Constructor for symbols with semantic value.
|
||||
basic_symbol (typename Base::kind_type t,
|
||||
const semantic_type& v,
|
||||
const location_type& l);
|
||||
|
||||
/// Destroy the symbol.
|
||||
~basic_symbol ();
|
||||
|
||||
/// Destroy contents, and record that is empty.
|
||||
void clear ();
|
||||
|
||||
/// Whether empty.
|
||||
bool empty () const;
|
||||
|
||||
/// Destructive move, \a s is emptied into this.
|
||||
void move (basic_symbol& s);
|
||||
|
||||
/// The semantic value.
|
||||
semantic_type value;
|
||||
|
||||
/// The location.
|
||||
location_type location;
|
||||
|
||||
private:
|
||||
/// Assignment operator.
|
||||
basic_symbol& operator= (const basic_symbol& other);
|
||||
};
|
||||
|
||||
/// Type access provider for token (enum) based symbols.
|
||||
struct by_type
|
||||
{
|
||||
/// Default constructor.
|
||||
by_type ();
|
||||
|
||||
/// Copy constructor.
|
||||
by_type (const by_type& other);
|
||||
|
||||
/// The symbol type as needed by the constructor.
|
||||
typedef token_type kind_type;
|
||||
|
||||
/// Constructor from (external) token numbers.
|
||||
by_type (kind_type t);
|
||||
|
||||
/// Record that this symbol is empty.
|
||||
void clear ();
|
||||
|
||||
/// Steal the symbol type from \a that.
|
||||
void move (by_type& that);
|
||||
|
||||
/// The (internal) type number (corresponding to \a type).
|
||||
/// \a empty when empty.
|
||||
symbol_number_type type_get () const;
|
||||
|
||||
/// The token.
|
||||
token_type token () const;
|
||||
|
||||
/// The symbol type.
|
||||
/// \a empty_symbol when empty.
|
||||
/// An int, not token_number_type, to be able to store empty_symbol.
|
||||
int type;
|
||||
};
|
||||
|
||||
/// "External" symbols: returned by the scanner.
|
||||
typedef basic_symbol<by_type> symbol_type;
|
||||
|
||||
|
||||
|
||||
/// Build a parser object.
|
||||
parser (iresearch::iql::context& ctx_yyarg);
|
||||
virtual ~parser ();
|
||||
|
||||
/// Parse.
|
||||
/// \returns 0 iff parsing succeeded.
|
||||
virtual int parse ();
|
||||
|
||||
/// The current debugging stream.
|
||||
std::ostream& debug_stream () const;
|
||||
/// Set the current debugging stream.
|
||||
void set_debug_stream (std::ostream &);
|
||||
|
||||
/// Type for debugging levels.
|
||||
typedef int debug_level_type;
|
||||
/// The current debugging level.
|
||||
debug_level_type debug_level () const;
|
||||
/// Set the current debugging level.
|
||||
void set_debug_level (debug_level_type l);
|
||||
|
||||
public:
|
||||
/// Report a syntax error.
|
||||
/// \param loc where the syntax error is found.
|
||||
/// \param msg a description of the syntax error.
|
||||
virtual void error (const location_type& loc, const std::string& msg);
|
||||
|
||||
# if YYDEBUG
|
||||
public:
|
||||
/// \brief Report a symbol value on the debug stream.
|
||||
/// \param yytype The token type.
|
||||
/// \param yyvaluep Its semantic value.
|
||||
/// \param yylocationp Its location.
|
||||
virtual void yy_symbol_value_print_ (int yytype,
|
||||
const semantic_type* yyvaluep,
|
||||
const location_type* yylocationp);
|
||||
/// \brief Report a symbol on the debug stream.
|
||||
/// \param yytype The token type.
|
||||
/// \param yyvaluep Its semantic value.
|
||||
/// \param yylocationp Its location.
|
||||
virtual void yy_symbol_print_ (int yytype,
|
||||
const semantic_type* yyvaluep,
|
||||
const location_type* yylocationp);
|
||||
private:
|
||||
// Debugging.
|
||||
std::ostream* yycdebug_;
|
||||
#endif
|
||||
|
||||
|
||||
// User arguments.
|
||||
iresearch::iql::context& ctx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifndef YYSTYPE
|
||||
# define YYSTYPE iresearch::iql::parser::semantic_type
|
||||
#endif
|
||||
#ifndef YYLTYPE
|
||||
# define YYLTYPE iresearch::iql::parser::location_type
|
||||
#endif
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // glr.cc:329
|
||||
} } // iresearch::iql
|
||||
#line 312 "parser.hh" // glr.cc:329
|
||||
// // "%code provides" blocks.
|
||||
#line 76 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // glr.cc:329
|
||||
|
||||
// ALWAYS!!! define YYDEBUG 1 for the length of the header so as to avoid
|
||||
// alignment issues when linkning without YYDEBUG agains a library that was
|
||||
// built with YYDEBUG or vice versa, reverse at end of header
|
||||
#ifdef YYDEBUG_REQUESTED
|
||||
#undef YYDEBUG_REQUESTED
|
||||
#else
|
||||
#undef YYDEBUG
|
||||
#define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
// end of suppress of warnings due to Bison generated code (pop section, push just above)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default : 4512)
|
||||
#endif
|
||||
|
||||
namespace iresearch {
|
||||
namespace iql {
|
||||
class context {
|
||||
public:
|
||||
// destructor
|
||||
virtual ~context() = default;
|
||||
|
||||
// parser operations
|
||||
virtual void yyerror(parser::location_type const& location, std::string const& sError) = 0;
|
||||
virtual parser::token_type yylex(parser::semantic_type& value, parser::location_type& location) = 0;
|
||||
|
||||
// value operations
|
||||
virtual parser::semantic_type sequence(parser::location_type const& location) = 0;
|
||||
|
||||
// node operations
|
||||
virtual parser::semantic_type append(parser::semantic_type const& value, parser::location_type const& location) = 0;
|
||||
virtual parser::semantic_type boost(parser::semantic_type const& value, parser::location_type const& location) = 0;
|
||||
virtual parser::semantic_type function(parser::semantic_type const& name, parser::semantic_type const& args) = 0;
|
||||
virtual parser::semantic_type list(parser::semantic_type const& value1, parser::semantic_type const& value2) = 0;
|
||||
virtual parser::semantic_type negation(parser::semantic_type const& value) = 0;
|
||||
virtual parser::semantic_type range(parser::semantic_type const& value1, bool bInclusive1, parser::semantic_type const& value2, bool bInclusive2) = 0;
|
||||
|
||||
// comparison operations
|
||||
virtual parser::semantic_type op_eq(parser::semantic_type const& value1, parser::semantic_type const& value2) = 0;
|
||||
virtual parser::semantic_type op_like(parser::semantic_type const& value1, parser::semantic_type const& value2) = 0;
|
||||
|
||||
// filter operations
|
||||
virtual parser::semantic_type op_and(parser::semantic_type const& value1, parser::semantic_type const& value2) = 0;
|
||||
virtual parser::semantic_type op_or(parser::semantic_type const& value1, parser::semantic_type const& value2) = 0;
|
||||
|
||||
// query operations
|
||||
virtual bool addOrder(parser::semantic_type const& value, bool bAscending = true) = 0;
|
||||
virtual bool setLimit(parser::semantic_type const& value) = 0;
|
||||
virtual bool setQuery(parser::semantic_type const& value) = 0;
|
||||
};
|
||||
|
||||
void debug(parser& parser, bool bEnable);
|
||||
|
||||
// this is required only for %skeleton "glr.cc" since it lacks default init
|
||||
// not needed for %skeleton "lalr1.cc" or without %skeleton
|
||||
#if YYDEBUG
|
||||
class location_type1: public location {};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#line 377 "parser.hh" // glr.cc:329
|
||||
|
||||
|
||||
#endif // !YY_YY_PARSER_HH_INCLUDED
|
|
@ -0,0 +1,169 @@
|
|||
// A Bison parser, made by GNU Bison 3.0.4.
|
||||
|
||||
// Positions for Bison parsers in C++
|
||||
|
||||
// Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// As a special exception, you may create a larger work that contains
|
||||
// part or all of the Bison parser skeleton and distribute that work
|
||||
// under terms of your choice, so long as that work isn't itself a
|
||||
// parser generator using the skeleton or a modified version thereof
|
||||
// as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
// the parser skeleton itself, you may (at your option) remove this
|
||||
// special exception, which will cause the skeleton and the resulting
|
||||
// Bison output files to be licensed under the GNU General Public
|
||||
// License without this special exception.
|
||||
|
||||
// This special exception was added by the Free Software Foundation in
|
||||
// version 2.2 of Bison.
|
||||
|
||||
/**
|
||||
** \file position.hh
|
||||
** Define the iresearch::iql::position class.
|
||||
*/
|
||||
|
||||
#ifndef YY_YY_POSITION_HH_INCLUDED
|
||||
# define YY_YY_POSITION_HH_INCLUDED
|
||||
|
||||
# include <algorithm> // std::max
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
|
||||
# ifndef YY_NULLPTR
|
||||
# if defined __cplusplus && 201103L <= __cplusplus
|
||||
# define YY_NULLPTR nullptr
|
||||
# else
|
||||
# define YY_NULLPTR 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // location.cc:296
|
||||
namespace iresearch { namespace iql {
|
||||
#line 56 "position.hh" // location.cc:296
|
||||
/// Abstract a position.
|
||||
class position
|
||||
{
|
||||
public:
|
||||
/// Initialization.
|
||||
void initialize (std::string* fn = YY_NULLPTR,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
{
|
||||
filename = fn;
|
||||
line = l;
|
||||
column = c;
|
||||
}
|
||||
|
||||
/** \name Line and Column related manipulators
|
||||
** \{ */
|
||||
/// (line related) Advance to the COUNT next lines.
|
||||
void lines (int count = 1)
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
column = 1u;
|
||||
line = add_ (line, count, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// (column related) Advance to the COUNT next columns.
|
||||
void columns (int count = 1)
|
||||
{
|
||||
column = add_ (column, count, 1);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/// File name to which this position refers.
|
||||
std::string* filename;
|
||||
/// Current line number.
|
||||
unsigned int line;
|
||||
/// Current column number.
|
||||
unsigned int column;
|
||||
|
||||
private:
|
||||
/// Compute max(min, lhs+rhs) (provided min <= lhs).
|
||||
static unsigned int add_ (unsigned int lhs, int rhs, unsigned int min)
|
||||
{
|
||||
return (0 < rhs || -static_cast<unsigned int>(rhs) < lhs
|
||||
? rhs + lhs
|
||||
: min);
|
||||
}
|
||||
};
|
||||
|
||||
/// Add \a width columns, in place.
|
||||
inline position&
|
||||
operator+= (position& res, int width)
|
||||
{
|
||||
res.columns (width);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Add \a width columns.
|
||||
inline position
|
||||
operator+ (position res, int width)
|
||||
{
|
||||
return res += width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns, in place.
|
||||
inline position&
|
||||
operator-= (position& res, int width)
|
||||
{
|
||||
return res += -width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns.
|
||||
inline position
|
||||
operator- (position res, int width)
|
||||
{
|
||||
return res -= width;
|
||||
}
|
||||
|
||||
/// Compare two position objects.
|
||||
inline bool
|
||||
operator== (const position& pos1, const position& pos2)
|
||||
{
|
||||
return (pos1.line == pos2.line
|
||||
&& pos1.column == pos2.column
|
||||
&& (pos1.filename == pos2.filename
|
||||
|| (pos1.filename && pos2.filename
|
||||
&& *pos1.filename == *pos2.filename)));
|
||||
}
|
||||
|
||||
/// Compare two position objects.
|
||||
inline bool
|
||||
operator!= (const position& pos1, const position& pos2)
|
||||
{
|
||||
return !(pos1 == pos2);
|
||||
}
|
||||
|
||||
/** \brief Intercept output stream redirection.
|
||||
** \param ostr the destination output stream
|
||||
** \param pos a reference to the position to redirect
|
||||
*/
|
||||
template <typename YYChar>
|
||||
inline std::basic_ostream<YYChar>&
|
||||
operator<< (std::basic_ostream<YYChar>& ostr, const position& pos)
|
||||
{
|
||||
if (pos.filename)
|
||||
ostr << *pos.filename << ':';
|
||||
return ostr << pos.line << '.' << pos.column;
|
||||
}
|
||||
|
||||
#line 31 "/home/user/git-root/arangodb-iresearch/3rdParty/iresearch/core/iql/parser.yy" // location.cc:296
|
||||
} } // iresearch::iql
|
||||
#line 169 "position.hh" // location.cc:296
|
||||
#endif // !YY_YY_POSITION_HH_INCLUDED
|
|
@ -0,0 +1,209 @@
|
|||
/* /home/user/git-root/arangodb-iresearch/build/qtcreator/Debug/3rdParty/iresearch/external/snowball/libstemmer/modules.h: List of stemming modules.
|
||||
*
|
||||
* This file is generated by mkmodules.pl from a list of module names.
|
||||
* Do not edit manually.
|
||||
*
|
||||
* Modules included by this file are: arabic, danish, dutch, english, finnish,
|
||||
* french, german, hungarian, irish, italian, norwegian, porter, portuguese,
|
||||
* romanian, russian, spanish, swedish, tamil, turkish
|
||||
*/
|
||||
|
||||
#include "../libstemmer/stem_UTF_8_arabic.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_danish.h"
|
||||
#include "../libstemmer/stem_UTF_8_danish.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_dutch.h"
|
||||
#include "../libstemmer/stem_UTF_8_dutch.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_english.h"
|
||||
#include "../libstemmer/stem_UTF_8_english.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_finnish.h"
|
||||
#include "../libstemmer/stem_UTF_8_finnish.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_french.h"
|
||||
#include "../libstemmer/stem_UTF_8_french.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_german.h"
|
||||
#include "../libstemmer/stem_UTF_8_german.h"
|
||||
#include "../libstemmer/stem_ISO_8859_2_hungarian.h"
|
||||
#include "../libstemmer/stem_UTF_8_hungarian.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_irish.h"
|
||||
#include "../libstemmer/stem_UTF_8_irish.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_italian.h"
|
||||
#include "../libstemmer/stem_UTF_8_italian.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_norwegian.h"
|
||||
#include "../libstemmer/stem_UTF_8_norwegian.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_porter.h"
|
||||
#include "../libstemmer/stem_UTF_8_porter.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_portuguese.h"
|
||||
#include "../libstemmer/stem_UTF_8_portuguese.h"
|
||||
#include "../libstemmer/stem_ISO_8859_2_romanian.h"
|
||||
#include "../libstemmer/stem_UTF_8_romanian.h"
|
||||
#include "../libstemmer/stem_KOI8_R_russian.h"
|
||||
#include "../libstemmer/stem_UTF_8_russian.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_spanish.h"
|
||||
#include "../libstemmer/stem_UTF_8_spanish.h"
|
||||
#include "../libstemmer/stem_ISO_8859_1_swedish.h"
|
||||
#include "../libstemmer/stem_UTF_8_swedish.h"
|
||||
#include "../libstemmer/stem_UTF_8_tamil.h"
|
||||
#include "../libstemmer/stem_UTF_8_turkish.h"
|
||||
|
||||
typedef enum {
|
||||
ENC_UNKNOWN=0,
|
||||
ENC_ISO_8859_1,
|
||||
ENC_ISO_8859_2,
|
||||
ENC_KOI8_R,
|
||||
ENC_UTF_8
|
||||
} stemmer_encoding_t;
|
||||
|
||||
struct stemmer_encoding {
|
||||
const char * name;
|
||||
stemmer_encoding_t enc;
|
||||
};
|
||||
static struct stemmer_encoding encodings[] = {
|
||||
{"ISO_8859_1", ENC_ISO_8859_1},
|
||||
{"ISO_8859_2", ENC_ISO_8859_2},
|
||||
{"KOI8_R", ENC_KOI8_R},
|
||||
{"UTF_8", ENC_UTF_8},
|
||||
{0,ENC_UNKNOWN}
|
||||
};
|
||||
|
||||
struct stemmer_modules {
|
||||
const char * name;
|
||||
stemmer_encoding_t enc;
|
||||
struct SN_env * (*create)(void);
|
||||
void (*close)(struct SN_env *);
|
||||
int (*stem)(struct SN_env *);
|
||||
};
|
||||
static struct stemmer_modules modules[] = {
|
||||
{"ar", ENC_UTF_8, arabic_UTF_8_create_env, arabic_UTF_8_close_env, arabic_UTF_8_stem},
|
||||
{"ara", ENC_UTF_8, arabic_UTF_8_create_env, arabic_UTF_8_close_env, arabic_UTF_8_stem},
|
||||
{"arabic", ENC_UTF_8, arabic_UTF_8_create_env, arabic_UTF_8_close_env, arabic_UTF_8_stem},
|
||||
{"da", ENC_ISO_8859_1, danish_ISO_8859_1_create_env, danish_ISO_8859_1_close_env, danish_ISO_8859_1_stem},
|
||||
{"da", ENC_UTF_8, danish_UTF_8_create_env, danish_UTF_8_close_env, danish_UTF_8_stem},
|
||||
{"dan", ENC_ISO_8859_1, danish_ISO_8859_1_create_env, danish_ISO_8859_1_close_env, danish_ISO_8859_1_stem},
|
||||
{"dan", ENC_UTF_8, danish_UTF_8_create_env, danish_UTF_8_close_env, danish_UTF_8_stem},
|
||||
{"danish", ENC_ISO_8859_1, danish_ISO_8859_1_create_env, danish_ISO_8859_1_close_env, danish_ISO_8859_1_stem},
|
||||
{"danish", ENC_UTF_8, danish_UTF_8_create_env, danish_UTF_8_close_env, danish_UTF_8_stem},
|
||||
{"de", ENC_ISO_8859_1, german_ISO_8859_1_create_env, german_ISO_8859_1_close_env, german_ISO_8859_1_stem},
|
||||
{"de", ENC_UTF_8, german_UTF_8_create_env, german_UTF_8_close_env, german_UTF_8_stem},
|
||||
{"deu", ENC_ISO_8859_1, german_ISO_8859_1_create_env, german_ISO_8859_1_close_env, german_ISO_8859_1_stem},
|
||||
{"deu", ENC_UTF_8, german_UTF_8_create_env, german_UTF_8_close_env, german_UTF_8_stem},
|
||||
{"dut", ENC_ISO_8859_1, dutch_ISO_8859_1_create_env, dutch_ISO_8859_1_close_env, dutch_ISO_8859_1_stem},
|
||||
{"dut", ENC_UTF_8, dutch_UTF_8_create_env, dutch_UTF_8_close_env, dutch_UTF_8_stem},
|
||||
{"dutch", ENC_ISO_8859_1, dutch_ISO_8859_1_create_env, dutch_ISO_8859_1_close_env, dutch_ISO_8859_1_stem},
|
||||
{"dutch", ENC_UTF_8, dutch_UTF_8_create_env, dutch_UTF_8_close_env, dutch_UTF_8_stem},
|
||||
{"en", ENC_ISO_8859_1, english_ISO_8859_1_create_env, english_ISO_8859_1_close_env, english_ISO_8859_1_stem},
|
||||
{"en", ENC_UTF_8, english_UTF_8_create_env, english_UTF_8_close_env, english_UTF_8_stem},
|
||||
{"eng", ENC_ISO_8859_1, english_ISO_8859_1_create_env, english_ISO_8859_1_close_env, english_ISO_8859_1_stem},
|
||||
{"eng", ENC_UTF_8, english_UTF_8_create_env, english_UTF_8_close_env, english_UTF_8_stem},
|
||||
{"english", ENC_ISO_8859_1, english_ISO_8859_1_create_env, english_ISO_8859_1_close_env, english_ISO_8859_1_stem},
|
||||
{"english", ENC_UTF_8, english_UTF_8_create_env, english_UTF_8_close_env, english_UTF_8_stem},
|
||||
{"es", ENC_ISO_8859_1, spanish_ISO_8859_1_create_env, spanish_ISO_8859_1_close_env, spanish_ISO_8859_1_stem},
|
||||
{"es", ENC_UTF_8, spanish_UTF_8_create_env, spanish_UTF_8_close_env, spanish_UTF_8_stem},
|
||||
{"esl", ENC_ISO_8859_1, spanish_ISO_8859_1_create_env, spanish_ISO_8859_1_close_env, spanish_ISO_8859_1_stem},
|
||||
{"esl", ENC_UTF_8, spanish_UTF_8_create_env, spanish_UTF_8_close_env, spanish_UTF_8_stem},
|
||||
{"fi", ENC_ISO_8859_1, finnish_ISO_8859_1_create_env, finnish_ISO_8859_1_close_env, finnish_ISO_8859_1_stem},
|
||||
{"fi", ENC_UTF_8, finnish_UTF_8_create_env, finnish_UTF_8_close_env, finnish_UTF_8_stem},
|
||||
{"fin", ENC_ISO_8859_1, finnish_ISO_8859_1_create_env, finnish_ISO_8859_1_close_env, finnish_ISO_8859_1_stem},
|
||||
{"fin", ENC_UTF_8, finnish_UTF_8_create_env, finnish_UTF_8_close_env, finnish_UTF_8_stem},
|
||||
{"finnish", ENC_ISO_8859_1, finnish_ISO_8859_1_create_env, finnish_ISO_8859_1_close_env, finnish_ISO_8859_1_stem},
|
||||
{"finnish", ENC_UTF_8, finnish_UTF_8_create_env, finnish_UTF_8_close_env, finnish_UTF_8_stem},
|
||||
{"fr", ENC_ISO_8859_1, french_ISO_8859_1_create_env, french_ISO_8859_1_close_env, french_ISO_8859_1_stem},
|
||||
{"fr", ENC_UTF_8, french_UTF_8_create_env, french_UTF_8_close_env, french_UTF_8_stem},
|
||||
{"fra", ENC_ISO_8859_1, french_ISO_8859_1_create_env, french_ISO_8859_1_close_env, french_ISO_8859_1_stem},
|
||||
{"fra", ENC_UTF_8, french_UTF_8_create_env, french_UTF_8_close_env, french_UTF_8_stem},
|
||||
{"fre", ENC_ISO_8859_1, french_ISO_8859_1_create_env, french_ISO_8859_1_close_env, french_ISO_8859_1_stem},
|
||||
{"fre", ENC_UTF_8, french_UTF_8_create_env, french_UTF_8_close_env, french_UTF_8_stem},
|
||||
{"french", ENC_ISO_8859_1, french_ISO_8859_1_create_env, french_ISO_8859_1_close_env, french_ISO_8859_1_stem},
|
||||
{"french", ENC_UTF_8, french_UTF_8_create_env, french_UTF_8_close_env, french_UTF_8_stem},
|
||||
{"ga", ENC_ISO_8859_1, irish_ISO_8859_1_create_env, irish_ISO_8859_1_close_env, irish_ISO_8859_1_stem},
|
||||
{"ga", ENC_UTF_8, irish_UTF_8_create_env, irish_UTF_8_close_env, irish_UTF_8_stem},
|
||||
{"ger", ENC_ISO_8859_1, german_ISO_8859_1_create_env, german_ISO_8859_1_close_env, german_ISO_8859_1_stem},
|
||||
{"ger", ENC_UTF_8, german_UTF_8_create_env, german_UTF_8_close_env, german_UTF_8_stem},
|
||||
{"german", ENC_ISO_8859_1, german_ISO_8859_1_create_env, german_ISO_8859_1_close_env, german_ISO_8859_1_stem},
|
||||
{"german", ENC_UTF_8, german_UTF_8_create_env, german_UTF_8_close_env, german_UTF_8_stem},
|
||||
{"gle", ENC_ISO_8859_1, irish_ISO_8859_1_create_env, irish_ISO_8859_1_close_env, irish_ISO_8859_1_stem},
|
||||
{"gle", ENC_UTF_8, irish_UTF_8_create_env, irish_UTF_8_close_env, irish_UTF_8_stem},
|
||||
{"hu", ENC_ISO_8859_2, hungarian_ISO_8859_2_create_env, hungarian_ISO_8859_2_close_env, hungarian_ISO_8859_2_stem},
|
||||
{"hu", ENC_UTF_8, hungarian_UTF_8_create_env, hungarian_UTF_8_close_env, hungarian_UTF_8_stem},
|
||||
{"hun", ENC_ISO_8859_2, hungarian_ISO_8859_2_create_env, hungarian_ISO_8859_2_close_env, hungarian_ISO_8859_2_stem},
|
||||
{"hun", ENC_UTF_8, hungarian_UTF_8_create_env, hungarian_UTF_8_close_env, hungarian_UTF_8_stem},
|
||||
{"hungarian", ENC_ISO_8859_2, hungarian_ISO_8859_2_create_env, hungarian_ISO_8859_2_close_env, hungarian_ISO_8859_2_stem},
|
||||
{"hungarian", ENC_UTF_8, hungarian_UTF_8_create_env, hungarian_UTF_8_close_env, hungarian_UTF_8_stem},
|
||||
{"irish", ENC_ISO_8859_1, irish_ISO_8859_1_create_env, irish_ISO_8859_1_close_env, irish_ISO_8859_1_stem},
|
||||
{"irish", ENC_UTF_8, irish_UTF_8_create_env, irish_UTF_8_close_env, irish_UTF_8_stem},
|
||||
{"it", ENC_ISO_8859_1, italian_ISO_8859_1_create_env, italian_ISO_8859_1_close_env, italian_ISO_8859_1_stem},
|
||||
{"it", ENC_UTF_8, italian_UTF_8_create_env, italian_UTF_8_close_env, italian_UTF_8_stem},
|
||||
{"ita", ENC_ISO_8859_1, italian_ISO_8859_1_create_env, italian_ISO_8859_1_close_env, italian_ISO_8859_1_stem},
|
||||
{"ita", ENC_UTF_8, italian_UTF_8_create_env, italian_UTF_8_close_env, italian_UTF_8_stem},
|
||||
{"italian", ENC_ISO_8859_1, italian_ISO_8859_1_create_env, italian_ISO_8859_1_close_env, italian_ISO_8859_1_stem},
|
||||
{"italian", ENC_UTF_8, italian_UTF_8_create_env, italian_UTF_8_close_env, italian_UTF_8_stem},
|
||||
{"nl", ENC_ISO_8859_1, dutch_ISO_8859_1_create_env, dutch_ISO_8859_1_close_env, dutch_ISO_8859_1_stem},
|
||||
{"nl", ENC_UTF_8, dutch_UTF_8_create_env, dutch_UTF_8_close_env, dutch_UTF_8_stem},
|
||||
{"nld", ENC_ISO_8859_1, dutch_ISO_8859_1_create_env, dutch_ISO_8859_1_close_env, dutch_ISO_8859_1_stem},
|
||||
{"nld", ENC_UTF_8, dutch_UTF_8_create_env, dutch_UTF_8_close_env, dutch_UTF_8_stem},
|
||||
{"no", ENC_ISO_8859_1, norwegian_ISO_8859_1_create_env, norwegian_ISO_8859_1_close_env, norwegian_ISO_8859_1_stem},
|
||||
{"no", ENC_UTF_8, norwegian_UTF_8_create_env, norwegian_UTF_8_close_env, norwegian_UTF_8_stem},
|
||||
{"nor", ENC_ISO_8859_1, norwegian_ISO_8859_1_create_env, norwegian_ISO_8859_1_close_env, norwegian_ISO_8859_1_stem},
|
||||
{"nor", ENC_UTF_8, norwegian_UTF_8_create_env, norwegian_UTF_8_close_env, norwegian_UTF_8_stem},
|
||||
{"norwegian", ENC_ISO_8859_1, norwegian_ISO_8859_1_create_env, norwegian_ISO_8859_1_close_env, norwegian_ISO_8859_1_stem},
|
||||
{"norwegian", ENC_UTF_8, norwegian_UTF_8_create_env, norwegian_UTF_8_close_env, norwegian_UTF_8_stem},
|
||||
{"por", ENC_ISO_8859_1, portuguese_ISO_8859_1_create_env, portuguese_ISO_8859_1_close_env, portuguese_ISO_8859_1_stem},
|
||||
{"por", ENC_UTF_8, portuguese_UTF_8_create_env, portuguese_UTF_8_close_env, portuguese_UTF_8_stem},
|
||||
{"porter", ENC_ISO_8859_1, porter_ISO_8859_1_create_env, porter_ISO_8859_1_close_env, porter_ISO_8859_1_stem},
|
||||
{"porter", ENC_UTF_8, porter_UTF_8_create_env, porter_UTF_8_close_env, porter_UTF_8_stem},
|
||||
{"portuguese", ENC_ISO_8859_1, portuguese_ISO_8859_1_create_env, portuguese_ISO_8859_1_close_env, portuguese_ISO_8859_1_stem},
|
||||
{"portuguese", ENC_UTF_8, portuguese_UTF_8_create_env, portuguese_UTF_8_close_env, portuguese_UTF_8_stem},
|
||||
{"pt", ENC_ISO_8859_1, portuguese_ISO_8859_1_create_env, portuguese_ISO_8859_1_close_env, portuguese_ISO_8859_1_stem},
|
||||
{"pt", ENC_UTF_8, portuguese_UTF_8_create_env, portuguese_UTF_8_close_env, portuguese_UTF_8_stem},
|
||||
{"ro", ENC_ISO_8859_2, romanian_ISO_8859_2_create_env, romanian_ISO_8859_2_close_env, romanian_ISO_8859_2_stem},
|
||||
{"ro", ENC_UTF_8, romanian_UTF_8_create_env, romanian_UTF_8_close_env, romanian_UTF_8_stem},
|
||||
{"romanian", ENC_ISO_8859_2, romanian_ISO_8859_2_create_env, romanian_ISO_8859_2_close_env, romanian_ISO_8859_2_stem},
|
||||
{"romanian", ENC_UTF_8, romanian_UTF_8_create_env, romanian_UTF_8_close_env, romanian_UTF_8_stem},
|
||||
{"ron", ENC_ISO_8859_2, romanian_ISO_8859_2_create_env, romanian_ISO_8859_2_close_env, romanian_ISO_8859_2_stem},
|
||||
{"ron", ENC_UTF_8, romanian_UTF_8_create_env, romanian_UTF_8_close_env, romanian_UTF_8_stem},
|
||||
{"ru", ENC_KOI8_R, russian_KOI8_R_create_env, russian_KOI8_R_close_env, russian_KOI8_R_stem},
|
||||
{"ru", ENC_UTF_8, russian_UTF_8_create_env, russian_UTF_8_close_env, russian_UTF_8_stem},
|
||||
{"rum", ENC_ISO_8859_2, romanian_ISO_8859_2_create_env, romanian_ISO_8859_2_close_env, romanian_ISO_8859_2_stem},
|
||||
{"rum", ENC_UTF_8, romanian_UTF_8_create_env, romanian_UTF_8_close_env, romanian_UTF_8_stem},
|
||||
{"rus", ENC_KOI8_R, russian_KOI8_R_create_env, russian_KOI8_R_close_env, russian_KOI8_R_stem},
|
||||
{"rus", ENC_UTF_8, russian_UTF_8_create_env, russian_UTF_8_close_env, russian_UTF_8_stem},
|
||||
{"russian", ENC_KOI8_R, russian_KOI8_R_create_env, russian_KOI8_R_close_env, russian_KOI8_R_stem},
|
||||
{"russian", ENC_UTF_8, russian_UTF_8_create_env, russian_UTF_8_close_env, russian_UTF_8_stem},
|
||||
{"spa", ENC_ISO_8859_1, spanish_ISO_8859_1_create_env, spanish_ISO_8859_1_close_env, spanish_ISO_8859_1_stem},
|
||||
{"spa", ENC_UTF_8, spanish_UTF_8_create_env, spanish_UTF_8_close_env, spanish_UTF_8_stem},
|
||||
{"spanish", ENC_ISO_8859_1, spanish_ISO_8859_1_create_env, spanish_ISO_8859_1_close_env, spanish_ISO_8859_1_stem},
|
||||
{"spanish", ENC_UTF_8, spanish_UTF_8_create_env, spanish_UTF_8_close_env, spanish_UTF_8_stem},
|
||||
{"sv", ENC_ISO_8859_1, swedish_ISO_8859_1_create_env, swedish_ISO_8859_1_close_env, swedish_ISO_8859_1_stem},
|
||||
{"sv", ENC_UTF_8, swedish_UTF_8_create_env, swedish_UTF_8_close_env, swedish_UTF_8_stem},
|
||||
{"swe", ENC_ISO_8859_1, swedish_ISO_8859_1_create_env, swedish_ISO_8859_1_close_env, swedish_ISO_8859_1_stem},
|
||||
{"swe", ENC_UTF_8, swedish_UTF_8_create_env, swedish_UTF_8_close_env, swedish_UTF_8_stem},
|
||||
{"swedish", ENC_ISO_8859_1, swedish_ISO_8859_1_create_env, swedish_ISO_8859_1_close_env, swedish_ISO_8859_1_stem},
|
||||
{"swedish", ENC_UTF_8, swedish_UTF_8_create_env, swedish_UTF_8_close_env, swedish_UTF_8_stem},
|
||||
{"ta", ENC_UTF_8, tamil_UTF_8_create_env, tamil_UTF_8_close_env, tamil_UTF_8_stem},
|
||||
{"tam", ENC_UTF_8, tamil_UTF_8_create_env, tamil_UTF_8_close_env, tamil_UTF_8_stem},
|
||||
{"tamil", ENC_UTF_8, tamil_UTF_8_create_env, tamil_UTF_8_close_env, tamil_UTF_8_stem},
|
||||
{"tr", ENC_UTF_8, turkish_UTF_8_create_env, turkish_UTF_8_close_env, turkish_UTF_8_stem},
|
||||
{"tur", ENC_UTF_8, turkish_UTF_8_create_env, turkish_UTF_8_close_env, turkish_UTF_8_stem},
|
||||
{"turkish", ENC_UTF_8, turkish_UTF_8_create_env, turkish_UTF_8_close_env, turkish_UTF_8_stem},
|
||||
{0,ENC_UNKNOWN,0,0,0}
|
||||
};
|
||||
static const char * algorithm_names[] = {
|
||||
"arabic",
|
||||
"danish",
|
||||
"dutch",
|
||||
"english",
|
||||
"finnish",
|
||||
"french",
|
||||
"german",
|
||||
"hungarian",
|
||||
"irish",
|
||||
"italian",
|
||||
"norwegian",
|
||||
"porter",
|
||||
"portuguese",
|
||||
"romanian",
|
||||
"russian",
|
||||
"spanish",
|
||||
"swedish",
|
||||
"tamil",
|
||||
"turkish",
|
||||
0
|
||||
};
|
|
@ -293,20 +293,24 @@ if(MSVC)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (USE_IQL)
|
||||
add_custom_command(
|
||||
OUTPUT iql/parser.cc
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy
|
||||
DEPENDS iql ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy
|
||||
COMMAND bison --graph --report=all -o parser.cc ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy
|
||||
WORKING_DIRECTORY iql
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT iql/parser.cc
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy
|
||||
DEPENDS iql ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy touch_iql_parser.cc
|
||||
COMMAND bison --graph --report=all -o parser.cc ${CMAKE_CURRENT_SOURCE_DIR}/iql/parser.yy
|
||||
WORKING_DIRECTORY iql
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT iql
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory iql
|
||||
)
|
||||
endif()
|
||||
add_custom_target(touch_iql_parser.cc
|
||||
DEPENDS iql
|
||||
COMMAND ${CMAKE_COMMAND} -E touch_nocreate parser.cc
|
||||
WORKING_DIRECTORY iql
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT iql
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory iql
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT utils
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef _MSC_VER
|
||||
#include <execinfo.h> // for backtrace(...)
|
||||
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && defined(__GLIBC__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
@ -38,13 +38,9 @@ void dump_mem_stats_trace() NOEXCEPT {
|
|||
#ifndef _MSC_VER
|
||||
|
||||
// MacOS does not have malloc.h and hence no mallinfo() or malloc_stats()
|
||||
#ifndef __APPLE__
|
||||
|
||||
// The following macro exists only in GLIBC, where we have mallinfo().
|
||||
// If it is not defined, we assume to be on libmusl or something like this
|
||||
// where we do not have mallinfo.
|
||||
|
||||
#ifdef M_ARENA_MAX
|
||||
// libmusl does no define mallinfo() or malloc_stats() in malloc.h
|
||||
// enable mallinfo() and malloc_stats() for GLIBC only
|
||||
#if !defined(__APPLE__) && defined(__GLIBC__)
|
||||
// ...........................................................................
|
||||
// output mallinfo()
|
||||
// ...........................................................................
|
||||
|
@ -81,7 +77,6 @@ Topmost releasable block (keepcost): %lu\n\
|
|||
// output malloc_stats()
|
||||
// ...........................................................................
|
||||
malloc_stats(); // outputs to stderr
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ...........................................................................
|
||||
|
@ -95,4 +90,4 @@ Topmost releasable block (keepcost): %lu\n\
|
|||
}
|
||||
|
||||
NS_END // memory
|
||||
NS_END
|
||||
NS_END
|
|
@ -17,11 +17,11 @@ INCLUDE(CheckCCompilerFlag)
|
|||
INCLUDE(FindPerl)
|
||||
|
||||
IF(NOT PERL_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Perl required to build snowball")
|
||||
MESSAGE(FATAL "Perl required to build snowball")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT STEMMER_SOURCE_DIR)
|
||||
MESSAGE(FATAL_ERROR "Source directory required to build snowball")
|
||||
MESSAGE(FATAL "Source directory required to build snowball")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CURRENT_SOURCE_DIR "${STEMMER_SOURCE_DIR}")
|
||||
|
@ -227,6 +227,7 @@ ADD_CUSTOM_TARGET(modules DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libstemmer/module
|
|||
SET(STEMMER_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/libstemmer/libstemmer.c")
|
||||
ADD_CUSTOM_TARGET(stemmer_deps ALL)
|
||||
ADD_DEPENDENCIES(stemmer_deps modules)
|
||||
ADD_DEPENDENCIES(stemmer_deps snowball) # ADD_CUSTOM_COMMAND(... DEPENDS snowball) does not always seem to apply
|
||||
|
||||
gen_stem("${LIBSTEM_ALGORITHMS}" "UTF_8")
|
||||
gen_stem("${KOI8_ALGORITHMS}" "KOI8_R")
|
||||
|
|
|
@ -6,7 +6,7 @@ integrate with and natively expose the full power of the
|
|||
[IResearch library](https://github.com/iresearch-toolkit/iresearch)
|
||||
to the ArangoDB user.
|
||||
|
||||
It provides the capability to:
|
||||
They provide the capability to:
|
||||
* evaluate together documents located in different collections
|
||||
* filter documents based on AQL boolean expressions and functions
|
||||
* sort the resultset based on how closely each document matched the filter
|
||||
|
@ -96,11 +96,11 @@ PHRASE(attribute-name,
|
|||
|
||||
Search for a phrase in the referenced attributes.
|
||||
|
||||
The phrase can be expressed as an arbitrary number of *phraseParts* optionally separated by *skipToken* number of tokens.
|
||||
The phrase can be expressed as an arbitrary number of *phraseParts* separated by *skipToken* number of tokens.
|
||||
|
||||
- *attribute-name* - the path of the attribute to compare against in the document
|
||||
- *phrasePart* - a string to search in the token stream; may consist of several words; will be split using the specified *analyzer*
|
||||
- *skipTokens* number of words or tokens to treat as wildcard
|
||||
- *skipTokens* number of words or tokens to treat as wildcards
|
||||
- *analyzer* - string with the analyzer used, i.e. *"text_en"* or [one of the other available string analyzers](../../../Manual/Views/ArangoSearch/Analyzers.html)
|
||||
|
||||
### STARTS_WITH()
|
||||
|
@ -109,7 +109,7 @@ The phrase can be expressed as an arbitrary number of *phraseParts* optionally s
|
|||
|
||||
Match the value of the **attribute-name** that starts with **prefix**
|
||||
|
||||
- *attribute-name* - the path of the attribute to compare agaainst in the document
|
||||
- *attribute-name* - the path of the attribute to compare against in the document
|
||||
- *prefix* - a string to search at the start of the text
|
||||
|
||||
### TOKENS()
|
||||
|
@ -164,13 +164,13 @@ or
|
|||
to match documents where 'description' contains a phrase 'quick brown'
|
||||
|
||||
FOR doc IN VIEW someView
|
||||
FILTER PHRASE(doc.description, 'quick brown', 'text_en')
|
||||
FILTER PHRASE(doc.description, [ 'quick brown' ], 'text_en')
|
||||
RETURN doc
|
||||
|
||||
or
|
||||
|
||||
FOR doc IN VIEW someView
|
||||
FILTER PHRASE(doc['description'], 'quick brown', 'text_en')
|
||||
FILTER PHRASE(doc['description'], [ 'quick brown' ], 'text_en')
|
||||
RETURN doc
|
||||
|
||||
to match documents where 'body' contains the phrase consisting of a sequence
|
||||
|
@ -178,13 +178,13 @@ like this:
|
|||
'quick' * 'fox jumps' (where the asterisk can be any single word)
|
||||
|
||||
FOR doc IN VIEW someView
|
||||
FILTER PHRASE(doc.body, 'quick', 1, 'fox jumps', 'text_en')
|
||||
FILTER PHRASE(doc.body, [ 'quick', 1, 'fox jumps' ], 'text_en')
|
||||
RETURN doc
|
||||
|
||||
or
|
||||
|
||||
FOR doc IN VIEW someView
|
||||
FILTER PHRASE(doc['body'], 'quick', 1, 'fox jumps', 'text_en')
|
||||
FILTER PHRASE(doc['body'], [ 'quick', 1, 'fox jumps' ], 'text_en')
|
||||
RETURN doc
|
||||
|
||||
to match documents where 'story' starts with 'In the beginning'
|
||||
|
|
|
@ -220,3 +220,6 @@ and - (dash) characters only. Please refer to
|
|||
[NamingConventions](../DataModeling/NamingConventions/CollectionNames.md) for
|
||||
more information on valid view names, which follow the same guidelines as
|
||||
collection names.
|
||||
|
||||
### IFF
|
||||
[if and only if](https://en.m.wikipedia.org/wiki/If_and_only_if)
|
||||
|
|
|
@ -201,24 +201,24 @@ During view modification the following directives apply:
|
|||
|
||||
* bytes: (optional; for default values use an empty object: `{}`)
|
||||
|
||||
* intervalStep: (optional, default: `10`; to disable use: `0`)
|
||||
apply consolidation policy with every Nth commit
|
||||
* segmentThreshold: (optional, default: `300`; to disable use: `0`)
|
||||
apply consolidation policy IFF {segmentThreshold} >= #segments
|
||||
|
||||
* threshold: (optional; default: `0.85`)
|
||||
consolidate `IFF {threshold} > segment_bytes / (all_segment_bytes / #segments)`
|
||||
|
||||
* bytes_accum: (optional; for default values use: `{}`)
|
||||
|
||||
* intervalStep: (optional; default: `10`; to disable use: `0`)
|
||||
apply consolidation policy with every Nth commit
|
||||
* segmentThreshold: (optional; default: `300`; to disable use: `0`)
|
||||
apply consolidation policy IFF {segmentThreshold} >= #segments
|
||||
|
||||
* threshold: (optional; default: `0.85`)
|
||||
consolidate `IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_bytes) / all_segment_bytes`
|
||||
|
||||
* count: (optional; for default values use: `{}`)
|
||||
|
||||
* intervalStep: (optional; default: `10`; to disable use: `0`)
|
||||
apply consolidation policy with every Nth commit
|
||||
* segmentThreshold: (optional; default: `300`; to disable use: `0`)
|
||||
apply consolidation policy IFF {segmentThreshold} >= #segments
|
||||
|
||||
* threshold: (optional; default: `0.85`)
|
||||
consolidate `IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #segments)`
|
||||
|
@ -226,8 +226,8 @@ During view modification the following directives apply:
|
|||
* fill: (optional)
|
||||
if specified, use empty object for default values, i.e. `{}`
|
||||
|
||||
* intervalStep: (optional; default: `10`; to disable use: `0`)
|
||||
apply consolidation policy with every Nth commit
|
||||
* segmentThreshold: (optional; default: `300`; to disable use: `0`)
|
||||
apply consolidation policy IFF {segmentThreshold} >= #segments
|
||||
|
||||
* threshold: (optional; default: `0.85`)
|
||||
consolidate `IFF {threshold} > #segment_docs{valid} / (#segment_docs{valid} + #segment_docs{removed})`
|
||||
|
|
|
@ -44,8 +44,8 @@ Specify properties for nested fields here
|
|||
@RESTSTRUCT{bytes,JSF_patch_api_view_props_consolidation,object,optional,JSF_patch_api_view_props_consolidation_bytes}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_patch_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_patch_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_patch_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (default: 0.85)
|
||||
|
@ -53,8 +53,8 @@ Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (d
|
|||
@RESTSTRUCT{bytes_accum,JSF_patch_api_view_props_consolidation,object,optional,JSF_patch_api_view_props_consolidation_bytes_accum}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_patch_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_patch_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_patch_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_bytes) / all_segment_bytes (default: 0.85)
|
||||
|
@ -62,8 +62,8 @@ Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_by
|
|||
@RESTSTRUCT{count,JSF_patch_api_view_props_consolidation,object,optional,JSF_patch_api_view_props_consolidation_count}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_patch_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_patch_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_patch_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #segments) (default: 0.85)
|
||||
|
@ -71,8 +71,8 @@ Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #
|
|||
@RESTSTRUCT{fill,JSF_patch_api_view_props_consolidation,object,optional,JSF_patch_api_view_props_consolidation_fill}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_patch_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_patch_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_patch_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > #segment_docs{valid} / (#segment_docs{valid} + #segment_docs{removed}) (default: 0.85)
|
||||
|
|
|
@ -17,8 +17,8 @@ should be a JSON object containing the following attributes:
|
|||
@RESTSTRUCT{bytes,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_bytes}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (default: 0.85)
|
||||
|
@ -26,8 +26,8 @@ Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (d
|
|||
@RESTSTRUCT{bytes_accum,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_bytes_accum}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_bytes) / all_segment_bytes (default: 0.85)
|
||||
|
@ -35,8 +35,8 @@ Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_by
|
|||
@RESTSTRUCT{count,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_count}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #segments) (default: 0.85)
|
||||
|
@ -44,8 +44,8 @@ Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #
|
|||
@RESTSTRUCT{fill,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_fill}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > #segment_docs{valid} / (#segment_docs{valid} + #segment_docs{removed}) (default: 0.85)
|
||||
|
|
|
@ -44,8 +44,8 @@ Specify properties for nested fields here
|
|||
@RESTSTRUCT{bytes,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_bytes}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_bytes,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (default: 0.85)
|
||||
|
@ -53,8 +53,8 @@ Consolidate IFF {threshold} > segment_bytes / (all_segment_bytes / #segments) (d
|
|||
@RESTSTRUCT{bytes_accum,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_bytes_accum}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_bytes_accum,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_bytes) / all_segment_bytes (default: 0.85)
|
||||
|
@ -62,8 +62,8 @@ Consolidate IFF {threshold} > (segment_bytes + sum_of_merge_candidate_segment_by
|
|||
@RESTSTRUCT{count,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_count}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_count,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #segments) (default: 0.85)
|
||||
|
@ -71,8 +71,8 @@ Consolidate IFF {threshold} > segment_docs{valid} / (all_segment_docs{valid} / #
|
|||
@RESTSTRUCT{fill,JSF_post_api_view_props_consolidation,object,optional,JSF_post_api_view_props_consolidation_fill}
|
||||
Use empty object for default values, i.e. {}
|
||||
|
||||
@RESTSTRUCT{intervalStep,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy with every Nth commit (default: 10, to disable use: 0)
|
||||
@RESTSTRUCT{segmentThreshold,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Apply consolidation policy IFF {segmentThreshold} >= #segments (default: 300, to disable use: 0)
|
||||
|
||||
@RESTSTRUCT{threshold,JSF_post_api_view_props_consolidation_fill,integer,optional,uint64}
|
||||
Consolidate IFF {threshold} > #segment_docs{valid} / (#segment_docs{valid} + #segment_docs{removed}) (default: 0.85)
|
||||
|
|
|
@ -51,14 +51,16 @@ template<typename T>
|
|||
class AsyncValue {
|
||||
typedef irs::async_utils::read_write_mutex::read_mutex ReadMutex;
|
||||
public:
|
||||
AsyncValue(): _readMutex(_mutex) {}
|
||||
T get() const { return _value.load(); }
|
||||
ReadMutex mutex() const { return ReadMutex(_mutex); } // prevent modification
|
||||
ReadMutex& mutex() const { return _readMutex; } // prevent modification
|
||||
|
||||
protected:
|
||||
mutable irs::async_utils::read_write_mutex _mutex; // read-lock to prevent value modification
|
||||
irs::async_utils::read_write_mutex _mutex; // read-lock to prevent value modification
|
||||
mutable ReadMutex _readMutex; // object that can be referenced by std::unique_lock
|
||||
std::atomic<T> _value;
|
||||
|
||||
explicit AsyncValue(T value): _value(value) {}
|
||||
explicit AsyncValue(T value): _readMutex(_mutex), _value(value) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -687,7 +687,7 @@ bool fromInArray(
|
|||
|
||||
bool attributeAccessFound = false;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
attributeAccessFound |= bool(arangodb::iresearch::checkAttributeAccess(
|
||||
attributeAccessFound |= (nullptr != arangodb::iresearch::checkAttributeAccess(
|
||||
valueNode->getMemberUnchecked(i), *ctx.ref
|
||||
));
|
||||
}
|
||||
|
@ -1208,6 +1208,7 @@ bool fromFuncExists(
|
|||
}
|
||||
|
||||
// PHRASE(<attribute>, <value> [, <offset>, <value>, ...], <analyzer>)
|
||||
// PHRASE(<attribute>, '[' <value> [, <offset>, <value>, ...] ']', <analyzer>)
|
||||
bool fromFuncPhrase(
|
||||
irs::boolean_filter* filter,
|
||||
arangodb::iresearch::QueryContext const& ctx,
|
||||
|
@ -1240,7 +1241,10 @@ bool fromFuncPhrase(
|
|||
return false;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// 1st argument defines a field
|
||||
// ...........................................................................
|
||||
|
||||
auto const* fieldArg = arangodb::iresearch::checkAttributeAccess(
|
||||
args.getMemberUnchecked(0), *ctx.ref
|
||||
);
|
||||
|
@ -1251,38 +1255,9 @@ bool fromFuncPhrase(
|
|||
return false;
|
||||
}
|
||||
|
||||
// 2nd argument defines a value
|
||||
auto const* valueArg = args.getMemberUnchecked(1);
|
||||
|
||||
if (!valueArg) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
irs::string_ref value;
|
||||
arangodb::iresearch::ScopedAqlValue inputValue(*valueArg);
|
||||
|
||||
if (filter || inputValue.isConstant()) {
|
||||
if (!inputValue.execute(ctx)) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: Failed to evaluate 2nd argument";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arangodb::iresearch::SCOPED_VALUE_TYPE_STRING != inputValue.type()) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument has invalid type '" << inputValue.type()
|
||||
<< "' (string expected)";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inputValue.getString(value)) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: Unable to parse 2nd argument as string";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// ...........................................................................
|
||||
// last argument defines the analyzer to use
|
||||
// ...........................................................................
|
||||
|
||||
auto const* analyzerArg = args.getMemberUnchecked(argc - 1);
|
||||
|
||||
|
@ -1336,6 +1311,66 @@ bool fromFuncPhrase(
|
|||
}
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// 2nd argument defines a value
|
||||
// ...........................................................................
|
||||
|
||||
auto const* valueArg = args.getMemberUnchecked(1);
|
||||
|
||||
if (!valueArg) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* valueArgs = &args;
|
||||
size_t valueArgsBegin = 1;
|
||||
size_t valueArgsEnd = argc - 1;
|
||||
|
||||
if (valueArg->isArray()) {
|
||||
valueArgs = valueArg;
|
||||
valueArgsBegin = 0;
|
||||
valueArgsEnd = valueArg->numMembers();
|
||||
|
||||
if (!(valueArgsEnd & 1)) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument has an invalid number of members (must be an odd number)";
|
||||
return false;
|
||||
}
|
||||
|
||||
valueArg = valueArgs->getMemberUnchecked(valueArgsBegin);
|
||||
|
||||
if (!valueArg) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument has an invalid member at offset: " << valueArg;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
irs::string_ref value;
|
||||
arangodb::iresearch::ScopedAqlValue inputValue(*valueArg);
|
||||
|
||||
if (filter || inputValue.isConstant()) {
|
||||
if (!inputValue.execute(ctx)) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: Failed to evaluate 2nd argument";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arangodb::iresearch::SCOPED_VALUE_TYPE_STRING != inputValue.type()) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: 2nd argument has invalid type '" << inputValue.type()
|
||||
<< "' (string expected)";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inputValue.getString(value)) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "'PHRASE' AQL function: Unable to parse 2nd argument as string";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
irs::by_phrase* phrase = nullptr;
|
||||
|
||||
if (filter) {
|
||||
|
@ -1359,8 +1394,8 @@ bool fromFuncPhrase(
|
|||
decltype(fieldArg) offsetArg = nullptr;
|
||||
size_t offset = 0;
|
||||
|
||||
for (size_t idx = 2, end = argc - 1; idx < end; idx += 2) {
|
||||
offsetArg = args.getMemberUnchecked(idx);
|
||||
for (size_t idx = valueArgsBegin + 1, end = valueArgsEnd; idx < end; idx += 2) {
|
||||
offsetArg = valueArgs->getMemberUnchecked(idx);
|
||||
|
||||
if (!offsetArg) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
|
@ -1368,7 +1403,7 @@ bool fromFuncPhrase(
|
|||
return false;
|
||||
}
|
||||
|
||||
valueArg = args.getMemberUnchecked(idx + 1);
|
||||
valueArg = valueArgs->getMemberUnchecked(idx + 1);
|
||||
|
||||
if (!valueArg) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
|
@ -1659,16 +1694,30 @@ NS_BEGIN(iresearch)
|
|||
) {
|
||||
auto filter = irs::And::make();
|
||||
|
||||
FilterFactory::filter(static_cast<irs::And&>(*filter), cid, rid);
|
||||
|
||||
return std::move(filter);
|
||||
}
|
||||
|
||||
/*static*/ irs::filter& FilterFactory::filter(
|
||||
irs::boolean_filter& buf,
|
||||
TRI_voc_cid_t cid,
|
||||
TRI_voc_rid_t rid
|
||||
) {
|
||||
// filter matching on cid and rid
|
||||
static_cast<irs::And&>(*filter).add<irs::by_term>()
|
||||
auto& filter = buf.add<irs::And>();
|
||||
|
||||
// filter matching on cid
|
||||
filter.add<irs::by_term>()
|
||||
.field(DocumentPrimaryKey::CID()) // set field
|
||||
.term(DocumentPrimaryKey::encode(cid)); // set value
|
||||
|
||||
static_cast<irs::And&>(*filter).add<irs::by_term>()
|
||||
// filter matching on rid
|
||||
filter.add<irs::by_term>()
|
||||
.field(DocumentPrimaryKey::RID()) // set field
|
||||
.term(DocumentPrimaryKey::encode(rid)); // set value
|
||||
|
||||
return std::move(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/*static*/ bool FilterFactory::filter(
|
||||
|
@ -1736,4 +1785,4 @@ NS_END // arangodb
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -49,6 +49,16 @@ struct FilterFactory {
|
|||
static irs::filter::ptr filter(TRI_voc_cid_t cid);
|
||||
static irs::filter::ptr filter(TRI_voc_cid_t cid, TRI_voc_rid_t rid);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a filter matching 'cid' + 'rid' pair and append to 'buf'
|
||||
/// @return the appended filter portion
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static irs::filter& filter(
|
||||
irs::boolean_filter& buf,
|
||||
TRI_voc_cid_t cid,
|
||||
TRI_voc_rid_t rid
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief determine if the 'node' can be converted into an iresearch filter
|
||||
/// if 'filter' != nullptr then also append the iresearch filter there
|
||||
|
|
|
@ -71,13 +71,29 @@ NS_END
|
|||
NS_BEGIN(arangodb)
|
||||
NS_BEGIN(iresearch)
|
||||
|
||||
IResearchLink::ViewRef::ViewRef(IResearchView::AsyncSelf::ptr const& view) {
|
||||
if (view && view->get()) {
|
||||
_view = view;
|
||||
_lock = std::unique_lock<ReadMutex>(_view->mutex());
|
||||
} else {
|
||||
static const arangodb::iresearch::IResearchView::AsyncSelf::ptr view =
|
||||
irs::memory::make_unique<arangodb::iresearch::IResearchView::AsyncSelf>(nullptr);
|
||||
|
||||
_view = view;
|
||||
}
|
||||
}
|
||||
|
||||
IResearchView* IResearchLink::ViewRef::get() const noexcept {
|
||||
return _view->get();
|
||||
}
|
||||
|
||||
IResearchLink::IResearchLink(
|
||||
TRI_idx_iid_t iid,
|
||||
arangodb::LogicalCollection* collection
|
||||
): _collection(collection),
|
||||
_defaultId(0), // 0 is never a valid id
|
||||
_id(iid),
|
||||
_view(NO_VIEW) {
|
||||
_view(nullptr) {
|
||||
}
|
||||
|
||||
IResearchLink::~IResearchLink() {
|
||||
|
@ -87,10 +103,7 @@ IResearchLink::~IResearchLink() {
|
|||
bool IResearchLink::operator==(IResearchView const& view) const noexcept {
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* thisView = _view->get();
|
||||
auto* thisView = _view.get();
|
||||
|
||||
return thisView && thisView->id() == view.id();
|
||||
}
|
||||
|
@ -138,10 +151,7 @@ void IResearchLink::batchInsert(
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
queue->setStatus(TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED); // IResearchView required
|
||||
|
@ -171,10 +181,7 @@ int IResearchLink::drop() {
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED; // IResearchView required
|
||||
|
@ -251,9 +258,9 @@ bool IResearchLink::init(arangodb::velocypack::Slice const& definition) {
|
|||
return false;
|
||||
}
|
||||
|
||||
auto viewSelf = view->self();
|
||||
ViewRef viewSelf(view->self());
|
||||
|
||||
if (!viewSelf) {
|
||||
if (!viewSelf.get()) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH) << "error getting view: '" << viewId << "' for link '" << _id << "'";
|
||||
|
||||
return false;
|
||||
|
@ -298,10 +305,7 @@ Result IResearchLink::insert(
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return TRI_ERROR_ARANGO_INDEX_HANDLE_BAD; // IResearchView required
|
||||
|
@ -340,10 +344,7 @@ bool IResearchLink::json(
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (view) {
|
||||
builder.add(VIEW_ID_FIELD, VPackValue(view->id()));
|
||||
|
@ -356,17 +357,15 @@ bool IResearchLink::json(
|
|||
}
|
||||
|
||||
void IResearchLink::load() {
|
||||
// Note: this function is only used by RocksDB
|
||||
}
|
||||
|
||||
bool IResearchLink::matchesDefinition(VPackSlice const& slice) const {
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
|
||||
if (slice.hasKey(VIEW_ID_FIELD)) {
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return false; // slice has identifier but the current object does not
|
||||
|
@ -377,7 +376,7 @@ bool IResearchLink::matchesDefinition(VPackSlice const& slice) const {
|
|||
if (!identifier.isNumber() || uint64_t(identifier.getInt()) != identifier.getUInt() || identifier.getUInt() != view->id()) {
|
||||
return false; // iResearch View names of current object and slice do not match
|
||||
}
|
||||
} else if (_view->get()) { // do not need to lock since this is a single-call
|
||||
} else if (_view.get()) { // do not need to lock since this is a single-call
|
||||
return false; // slice has no 'name' but the current object does
|
||||
}
|
||||
|
||||
|
@ -394,10 +393,7 @@ size_t IResearchLink::memory() const {
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (view) {
|
||||
size_t count = 0;
|
||||
|
@ -432,10 +428,7 @@ Result IResearchLink::remove(
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED; // IResearchView required
|
||||
|
@ -460,10 +453,7 @@ Result IResearchLink::remove(
|
|||
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED; // IResearchView required
|
||||
|
@ -496,6 +486,27 @@ Result IResearchLink::remove(
|
|||
return true;
|
||||
}
|
||||
|
||||
arangodb::Result IResearchLink::recover() {
|
||||
if (!_collection) {
|
||||
return {TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND}; // current link isn't associated with the collection
|
||||
}
|
||||
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
return {TRI_ERROR_ARANGO_VIEW_NOT_FOUND}; // slice has identifier but the current object does not
|
||||
}
|
||||
|
||||
arangodb::velocypack::Builder link;
|
||||
|
||||
if (!json(link, false)) {
|
||||
return {TRI_ERROR_INTERNAL};
|
||||
}
|
||||
|
||||
// re-insert link into the view
|
||||
return view->link(_collection->cid(), link.slice());
|
||||
}
|
||||
|
||||
Index::IndexType IResearchLink::type() const {
|
||||
// TODO: don't use enum
|
||||
return Index::TRI_IDX_TYPE_IRESEARCH_LINK;
|
||||
|
@ -508,14 +519,10 @@ char const* IResearchLink::typeName() const {
|
|||
int IResearchLink::unload() {
|
||||
WriteMutex mutex(_mutex); // '_view' can be asynchronously read
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
auto viewCopy = _view; // retain a copy of the pointer for the case where nullyfying the original will call distructor of a locked mutex
|
||||
auto viewMutex = _view->mutex(); // IResearchView can be asynchronously deallocated
|
||||
SCOPED_LOCK(viewMutex);
|
||||
auto* view = _view->get();
|
||||
auto* view = _view.get();
|
||||
|
||||
if (!view) {
|
||||
_view = NO_VIEW; // release reference to the IResearch View
|
||||
_view = ViewRef(nullptr); // release reference to the IResearch View
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -543,7 +550,7 @@ int IResearchLink::unload() {
|
|||
}
|
||||
}
|
||||
|
||||
_view = NO_VIEW; // release reference to the iResearch View
|
||||
_view = ViewRef(nullptr); // release reference to the IResearch View
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -551,9 +558,8 @@ int IResearchLink::unload() {
|
|||
const IResearchView* IResearchLink::view() const {
|
||||
ReadMutex mutex(_mutex); // '_view' can be asynchronously modified
|
||||
SCOPED_LOCK(mutex);
|
||||
assert(_view); // NO_VIEW used for unasociated links
|
||||
|
||||
return _view->get();
|
||||
return _view.get();
|
||||
}
|
||||
|
||||
int EnhanceJsonIResearchLink(
|
||||
|
|
|
@ -159,6 +159,13 @@ class IResearchLink {
|
|||
TRI_voc_cid_t value
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief recover IResearch Link index in a view by dropping existing and
|
||||
/// creating a new one
|
||||
/// @return success
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
arangodb::Result recover();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief iResearch Link index type enum value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -199,12 +206,22 @@ class IResearchLink {
|
|||
// the update delta into the WAL marker instead of the full persisted state
|
||||
friend arangodb::Result IResearchView::updateProperties(arangodb::velocypack::Slice const&, bool, bool);
|
||||
|
||||
class ViewRef {
|
||||
public:
|
||||
ViewRef(IResearchView::AsyncSelf::ptr const& view);
|
||||
IResearchView* get() const noexcept;
|
||||
|
||||
private:
|
||||
std::unique_lock<irs::async_utils::read_write_mutex::read_mutex> _lock;
|
||||
IResearchView::AsyncSelf::ptr _view;
|
||||
};
|
||||
|
||||
LogicalCollection* _collection; // the linked collection
|
||||
TRI_voc_cid_t _defaultId; // the identifier of the desired view (iff _view == nullptr)
|
||||
TRI_idx_iid_t const _id; // the index identifier
|
||||
IResearchLinkMeta _meta; // how this collection should be indexed
|
||||
mutable irs::async_utils::read_write_mutex _mutex; // for use with _view to allow asynchronous disassociation
|
||||
IResearchView::AsyncSelf::ptr _view; // effectively the IResearch datastore itself (nullptr == not associated)
|
||||
ViewRef _view; // effectively the IResearch datastore itself (nullptr == not associated)
|
||||
}; // IResearchLink
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -46,7 +46,7 @@ class IResearchMMFilesLink final
|
|||
transaction::Methods* trx,
|
||||
std::vector<std::pair<arangodb::LocalDocumentId, arangodb::velocypack::Slice>> const& documents,
|
||||
std::shared_ptr<arangodb::basics::LocalTaskQueue> queue
|
||||
) {
|
||||
) override {
|
||||
IResearchLink::batchInsert(trx, documents, queue);
|
||||
}
|
||||
|
||||
|
@ -152,4 +152,4 @@ class IResearchMMFilesLink final
|
|||
NS_END // iresearch
|
||||
NS_END // arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -46,7 +46,7 @@ class IResearchRocksDBLink final
|
|||
transaction::Methods* trx,
|
||||
std::vector<std::pair<arangodb::LocalDocumentId, arangodb::velocypack::Slice>> const& documents,
|
||||
std::shared_ptr<arangodb::basics::LocalTaskQueue> queue
|
||||
) {
|
||||
) override {
|
||||
IResearchLink::batchInsert(trx, documents, queue);
|
||||
}
|
||||
|
||||
|
@ -152,4 +152,4 @@ class IResearchRocksDBLink final
|
|||
NS_END // iresearch
|
||||
NS_END // arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -316,6 +316,117 @@ inline void insertDocument(
|
|||
doc.insert(irs::action::store, primaryKey);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief syncs an IResearch DataStore if required
|
||||
/// @return a sync was executed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool syncStore(
|
||||
irs::directory& directory,
|
||||
irs::directory_reader& reader,
|
||||
irs::index_writer& writer,
|
||||
std::atomic<size_t>& segmentCount,
|
||||
arangodb::iresearch::IResearchViewMeta::CommitMeta::ConsolidationPolicies const& policies,
|
||||
bool forceCommit,
|
||||
bool runCleanupAfterCommit,
|
||||
std::string const& viewName
|
||||
) {
|
||||
char runId = 0; // value not used
|
||||
|
||||
// ...........................................................................
|
||||
// apply consolidation policies
|
||||
// ...........................................................................
|
||||
|
||||
for (auto& entry: policies) {
|
||||
if (!entry.segmentThreshold()
|
||||
|| entry.segmentThreshold() > segmentCount.load()) {
|
||||
continue; // skip if interval not reached or no valid policy to execute
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "registering consolidation policy '" << size_t(entry.type()) << "' with IResearch view '" << viewName << "' run id '" << size_t(&runId) << " segment threshold '" << entry.segmentThreshold() << "' segment count '" << segmentCount.load() << "'";
|
||||
|
||||
try {
|
||||
writer.consolidate(entry.policy(), false);
|
||||
forceCommit = true; // a consolidation policy was found requiring commit
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during registeration of consolidation policy '" << size_t(entry.type()) << "' with IResearch view '" << viewName << "': " << e.what();
|
||||
IR_EXCEPTION();
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during registeration of consolidation policy '" << size_t(entry.type()) << "' with IResearch view '" << viewName << "'";
|
||||
IR_EXCEPTION();
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished registering consolidation policy '" << size_t(entry.type()) << "' with IResearch view '" << viewName << "' run id '" << size_t(&runId) << "'";
|
||||
}
|
||||
|
||||
if (!forceCommit) {
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "skipping store sync since no consolidation policies matched and sync not forced for IResearch view '" << viewName << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
return false; // commit not done
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// apply data store commit
|
||||
// ...........................................................................
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting store sync for IResearch view '" << viewName << "' run id '" << size_t(&runId) << "' segment count before '" << segmentCount.load() << "'";
|
||||
|
||||
try {
|
||||
segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
writer.commit();
|
||||
reader = reader.reopen(); // update reader
|
||||
segmentCount += reader.size(); // add commited segments
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during sync of IResearch view '" << viewName << "': " << e.what();
|
||||
IR_EXCEPTION();
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during sync of IResearch view '" << viewName << "'";
|
||||
IR_EXCEPTION();
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished store sync for IResearch view '" << viewName << "' run id '" << size_t(&runId) << "' segment count after '" << segmentCount.load() << "'";
|
||||
|
||||
if (!runCleanupAfterCommit) {
|
||||
return true; // commit done
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// apply cleanup
|
||||
// ...........................................................................
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting cleanup for IResearch view '" << viewName << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
try {
|
||||
irs::directory_utils::remove_all_unreferenced(directory);
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during cleanup of IResearch view '" << viewName << "': " << e.what();
|
||||
IR_EXCEPTION();
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during cleanup of IResearch view '" << viewName << "'";
|
||||
IR_EXCEPTION();
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished cleanup for IResearch view '" << viewName << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates the collections in 'vocbase' to match the specified
|
||||
/// IResearchLink definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
arangodb::Result updateLinks(
|
||||
std::unordered_set<TRI_voc_cid_t>& modified,
|
||||
TRI_vocbase_t& vocbase,
|
||||
|
@ -679,8 +790,10 @@ IResearchView::DataStore& IResearchView::DataStore::operator=(
|
|||
|
||||
void IResearchView::DataStore::sync() {
|
||||
TRI_ASSERT(_writer && _reader);
|
||||
_segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
_writer->commit();
|
||||
_reader = _reader.reopen(); // update reader
|
||||
_segmentCount += _reader.size(); // add commited segments
|
||||
}
|
||||
|
||||
IResearchView::MemoryStore::MemoryStore() {
|
||||
|
@ -694,32 +807,6 @@ IResearchView::MemoryStore::MemoryStore() {
|
|||
_reader = irs::directory_reader::open(*_directory); // open after 'commit' for valid 'store'
|
||||
}
|
||||
|
||||
IResearchView::SyncState::PolicyState::PolicyState(
|
||||
size_t intervalStep,
|
||||
const std::shared_ptr<irs::index_writer::consolidation_policy_t>& policy
|
||||
): _intervalCount(0), _intervalStep(intervalStep), _policy(policy) {
|
||||
}
|
||||
|
||||
IResearchView::SyncState::SyncState() noexcept
|
||||
: _cleanupIntervalCount(0),
|
||||
_cleanupIntervalStep(0) {
|
||||
}
|
||||
|
||||
IResearchView::SyncState::SyncState(
|
||||
IResearchViewMeta::CommitMeta const& meta
|
||||
): SyncState() {
|
||||
_cleanupIntervalStep = meta._cleanupIntervalStep;
|
||||
|
||||
for (auto& entry: meta._consolidationPolicies) {
|
||||
if (entry.policy()) {
|
||||
_consolidationPolicies.emplace_back(
|
||||
entry.intervalStep(),
|
||||
irs::memory::make_unique<irs::index_writer::consolidation_policy_t>(entry.policy())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IResearchView::TidStore::TidStore(
|
||||
transaction::Methods& trx,
|
||||
std::function<void(transaction::Methods*)> const& trxCallback
|
||||
|
@ -838,79 +925,106 @@ IResearchView::IResearchView(
|
|||
};
|
||||
|
||||
// add asynchronous commit job
|
||||
_threadPool.run(
|
||||
[this]()->void {
|
||||
struct State: public SyncState {
|
||||
size_t _asyncMetaRevision;
|
||||
size_t _commitIntervalMsecRemainder;
|
||||
size_t _commitTimeoutMsec;
|
||||
|
||||
State():
|
||||
SyncState(),
|
||||
_asyncMetaRevision(0), // '0' differs from IResearchView constructor above
|
||||
_commitIntervalMsecRemainder(std::numeric_limits<size_t>::max()),
|
||||
_commitTimeoutMsec(0) {
|
||||
}
|
||||
explicit State(IResearchViewMeta::CommitMeta const& meta)
|
||||
: SyncState(meta),
|
||||
_asyncMetaRevision(0), // '0' differs from IResearchView constructor above
|
||||
_commitIntervalMsecRemainder(std::numeric_limits<size_t>::max()),
|
||||
_commitTimeoutMsec(meta._commitTimeoutMsec) {
|
||||
}
|
||||
_threadPool.run([this]()->void {
|
||||
struct DataStoreState {
|
||||
size_t _cleanupIntervalCount;
|
||||
DataStore& _dataStore;
|
||||
DataStoreState(DataStore& store)
|
||||
: _cleanupIntervalCount(0), _dataStore(store) {}
|
||||
};
|
||||
|
||||
State state;
|
||||
size_t asyncMetaRevision = 0; // '0' differs from IResearchView constructor above
|
||||
size_t cleanupIntervalStep; // will be initialized when states are updated below
|
||||
auto commitIntervalMsecRemainder = std::numeric_limits<size_t>::max(); // longest possible time for std::min(...)
|
||||
size_t commitTimeoutMsec; // will be initialized when states are updated below
|
||||
IResearchViewMeta::CommitMeta::ConsolidationPolicies consolidationPolicies;
|
||||
DataStoreState states[] = {
|
||||
DataStoreState(_memoryNodes[0]._store),
|
||||
DataStoreState(_memoryNodes[1]._store),
|
||||
DataStoreState(_storePersisted)
|
||||
};
|
||||
ReadMutex mutex(_mutex); // '_meta' can be asynchronously modified
|
||||
|
||||
for(;;) {
|
||||
bool commitTimeoutReached = false;
|
||||
|
||||
// sleep until timeout
|
||||
{
|
||||
SCOPED_LOCK_NAMED(mutex, lock); // for '_meta._commit._commitIntervalMsec'
|
||||
SCOPED_LOCK_NAMED(_asyncMutex, asyncLock); // aquire before '_asyncTerminate' check
|
||||
|
||||
if (_asyncTerminate.load()) {
|
||||
break;
|
||||
return; // termination requested
|
||||
}
|
||||
|
||||
if (!_meta._commit._commitIntervalMsec) {
|
||||
lock.unlock(); // do not hold read lock while waiting on condition
|
||||
_asyncCondition.wait(asyncLock); // wait forever
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
auto msecRemainder =
|
||||
std::min(commitIntervalMsecRemainder, _meta._commit._commitIntervalMsec);
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
auto endTime = startTime + std::chrono::milliseconds(msecRemainder);
|
||||
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
auto endTime = startTime
|
||||
+ std::chrono::milliseconds(std::min(state._commitIntervalMsecRemainder, _meta._commit._commitIntervalMsec))
|
||||
;
|
||||
lock.unlock(); // do not hold read lock while waiting on condition
|
||||
commitIntervalMsecRemainder = std::numeric_limits<size_t>::max(); // longest possible time assuming an uninterrupted sleep
|
||||
commitTimeoutReached = true;
|
||||
|
||||
lock.unlock(); // do not hold read lock while waiting on condition
|
||||
state._commitIntervalMsecRemainder = std::numeric_limits<size_t>::max(); // longest possible time assuming an uninterrupted sleep
|
||||
if (std::cv_status::timeout != _asyncCondition.wait_until(asyncLock, endTime)) {
|
||||
auto nowTime = std::chrono::system_clock::now();
|
||||
|
||||
if (std::cv_status::timeout != _asyncCondition.wait_until(asyncLock, endTime)) {
|
||||
auto nowTime = std::chrono::system_clock::now();
|
||||
|
||||
// if still need to sleep more then must relock '_meta' and sleep for min (remainder, interval)
|
||||
if (nowTime < endTime) {
|
||||
state._commitIntervalMsecRemainder = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - nowTime).count();
|
||||
|
||||
continue; // need to reaquire lock to chech for change in '_meta'
|
||||
// if still need to sleep more then must relock '_meta' and sleep for min (remainder, interval)
|
||||
if (nowTime < endTime) {
|
||||
commitIntervalMsecRemainder = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - nowTime).count();
|
||||
commitTimeoutReached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_asyncTerminate.load()) {
|
||||
break;
|
||||
return; // termination requested
|
||||
}
|
||||
}
|
||||
|
||||
// reload state if required
|
||||
if (_asyncMetaRevision.load() != state._asyncMetaRevision) {
|
||||
SCOPED_LOCK(mutex);
|
||||
state = State(_meta._commit);
|
||||
state._asyncMetaRevision = _asyncMetaRevision.load();
|
||||
SCOPED_LOCK(mutex); // '_meta'/'_memoryStore'/'_storePersisted' can be asynchronously modified
|
||||
|
||||
// reload states if required
|
||||
if (_asyncMetaRevision.load() != asyncMetaRevision) {
|
||||
asyncMetaRevision = _asyncMetaRevision.load();
|
||||
cleanupIntervalStep = _meta._commit._cleanupIntervalStep;
|
||||
commitTimeoutMsec = _meta._commit._commitTimeoutMsec;
|
||||
consolidationPolicies = _meta._commit._consolidationPolicies; // local copy
|
||||
}
|
||||
|
||||
auto thresholdSec = TRI_microtime() + commitTimeoutMsec/1000.0;
|
||||
|
||||
// perform sync
|
||||
sync(state, state._commitTimeoutMsec);
|
||||
for (size_t i = 0, count = IRESEARCH_COUNTOF(states);
|
||||
i < count && TRI_microtime() <= thresholdSec;
|
||||
++i) {
|
||||
auto& state = states[i];
|
||||
auto runCleanupAfterCommit =
|
||||
state._cleanupIntervalCount > cleanupIntervalStep;
|
||||
|
||||
if (state._dataStore._directory
|
||||
&& state._dataStore._writer
|
||||
&& syncStore(*(state._dataStore._directory),
|
||||
state._dataStore._reader,
|
||||
*(state._dataStore._writer),
|
||||
state._dataStore._segmentCount,
|
||||
consolidationPolicies,
|
||||
commitTimeoutReached,
|
||||
runCleanupAfterCommit,
|
||||
name()
|
||||
)) {
|
||||
commitIntervalMsecRemainder = std::numeric_limits<size_t>::max(); // longest possible time for std::min(...)
|
||||
|
||||
if (runCleanupAfterCommit
|
||||
&& ++state._cleanupIntervalCount >= cleanupIntervalStep) {
|
||||
state._cleanupIntervalCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -952,55 +1066,6 @@ IResearchView::MemoryStore& IResearchView::activeMemoryStore() const {
|
|||
return _memoryNode->_store;
|
||||
}
|
||||
|
||||
bool IResearchView::cleanup(size_t maxMsec /*= 0*/) {
|
||||
ReadMutex mutex(_mutex);
|
||||
auto thresholdSec = TRI_microtime() + maxMsec/1000.0;
|
||||
|
||||
try {
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting active memory-store cleanup for iResearch view '" << id() << "'";
|
||||
irs::directory_utils::remove_all_unreferenced(*(_memoryNode->_store._directory));
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished active memory-store cleanup for iResearch view '" << id() << "'";
|
||||
|
||||
if (maxMsec && TRI_microtime() >= thresholdSec) {
|
||||
return true; // skip if timout exceeded
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting flushing memory-store cleanup for iResearch view '" << id() << "'";
|
||||
irs::directory_utils::remove_all_unreferenced(*(_toFlush->_store._directory));
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished flushing memory-store cleanup for iResearch view '" << id() << "'";
|
||||
|
||||
if (maxMsec && TRI_microtime() >= thresholdSec) {
|
||||
return true; // skip if timout exceeded
|
||||
}
|
||||
|
||||
if (_storePersisted) {
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting persisted-store cleanup for iResearch view '" << id() << "'";
|
||||
irs::directory_utils::remove_all_unreferenced(*(_storePersisted._directory));
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished persisted-store cleanup for iResearch view '" << id() << "'";
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during cleanup of iResearch view '" << id() << "': " << e.what();
|
||||
IR_EXCEPTION();
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception during cleanup of iResearch view '" << id() << "'";
|
||||
IR_EXCEPTION();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void IResearchView::drop() {
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
|
||||
|
@ -1173,6 +1238,8 @@ int IResearchView::finish(TRI_voc_tid_t tid, bool commit) {
|
|||
|
||||
trxStore._writer->commit(); // ensure have latest view in reader
|
||||
memoryStore._writer->import(trxStore._reader.reopen());
|
||||
++memoryStore._segmentCount; // a new segment was imported
|
||||
_asyncCondition.notify_all(); // trigger recheck of sync
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
} catch (std::exception const& e) {
|
||||
|
@ -1214,12 +1281,18 @@ arangodb::Result IResearchView::commit() {
|
|||
}
|
||||
|
||||
SCOPED_LOCK(_toFlush->_reopenMutex); // do not allow concurrent reopen
|
||||
_storePersisted._segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
_storePersisted._writer->commit(); // finishing flush transaction
|
||||
memoryStore._segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
memoryStore._writer->clear(); // prepare the store for reuse
|
||||
|
||||
SCOPED_LOCK(_toFlush->_readMutex); // do not allow concurrent read since _storePersisted/_toFlush need to be updated atomically
|
||||
_storePersisted._reader = _storePersisted._reader.reopen(); // update reader
|
||||
_storePersisted._segmentCount += _storePersisted._reader.size(); // add commited segments
|
||||
memoryStore._reader = memoryStore._reader.reopen(); // update reader
|
||||
memoryStore._segmentCount += memoryStore._reader.size(); // add commited segments
|
||||
|
||||
_asyncCondition.notify_all(); // trigger recheck of sync
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
} catch (std::exception const& e) {
|
||||
|
@ -1485,6 +1558,55 @@ int IResearchView::insert(
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
arangodb::Result IResearchView::link(
|
||||
TRI_voc_cid_t cid,
|
||||
arangodb::velocypack::Slice const link
|
||||
) {
|
||||
if (!_logicalView) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to find logical view while linking IResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
auto* vocbase = _logicalView->vocbase();
|
||||
|
||||
if (!vocbase) {
|
||||
return arangodb::Result(
|
||||
TRI_ERROR_INTERNAL,
|
||||
std::string("failed to find vocbase while linking IResearch view '") + std::to_string(id()) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
||||
builder.openObject();
|
||||
builder.add(
|
||||
std::to_string(cid),
|
||||
arangodb::velocypack::Value(arangodb::velocypack::ValueType::Null)
|
||||
);
|
||||
|
||||
if (link.isObject()) {
|
||||
builder.add(std::to_string(cid), link);
|
||||
}
|
||||
|
||||
builder.close();
|
||||
|
||||
std::unordered_set<TRI_voc_cid_t> collections;
|
||||
auto result = updateLinks(collections, *vocbase, *this, builder.slice());
|
||||
|
||||
if (result.ok()) {
|
||||
WriteMutex mutex(_mutex); // '_meta' can be asynchronously read
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
collections.insert(_meta._collections.begin(), _meta._collections.end());
|
||||
validateLinks(collections, *vocbase, *this); // remove invalid cids (no such collection or no such link)
|
||||
_meta._collections = std::move(collections);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*static*/ IResearchView::ptr IResearchView::make(
|
||||
arangodb::LogicalView* view,
|
||||
arangodb::velocypack::Slice const& info,
|
||||
|
@ -1719,11 +1841,13 @@ bool IResearchView::sync(size_t maxMsec /*= 0*/) {
|
|||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting pending memory-store sync for iResearch view '" << id() << "'";
|
||||
_toFlush->_store._segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
_toFlush->_store._writer->commit();
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_toFlush->_reopenMutex);
|
||||
_toFlush->_store._reader = _toFlush->_store._reader.reopen(); // update reader
|
||||
_toFlush->_store._segmentCount += _toFlush->_store._reader.size(); // add commited segments
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
|
@ -1737,11 +1861,13 @@ bool IResearchView::sync(size_t maxMsec /*= 0*/) {
|
|||
if (_storePersisted) {
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting persisted-sync sync for iResearch view '" << id() << "'";
|
||||
_storePersisted._segmentCount.store(0); // reset to zero to get count of new segments that appear during commit
|
||||
_storePersisted._writer->commit();
|
||||
|
||||
{
|
||||
SCOPED_LOCK(_toFlush->_reopenMutex);
|
||||
_storePersisted._reader = _storePersisted._reader.reopen(); // update reader
|
||||
_storePersisted._segmentCount += _storePersisted._reader.size(); // add commited segments
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
|
@ -1762,81 +1888,6 @@ bool IResearchView::sync(size_t maxMsec /*= 0*/) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IResearchView::sync(SyncState& state, size_t maxMsec /*= 0*/) {
|
||||
char runId = 0; // value not used
|
||||
auto thresholdMsec = TRI_microtime() * 1000 + maxMsec;
|
||||
ReadMutex mutex(_mutex); // '_memoryStore'/'_storePersisted' can be asynchronously modified
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting flush for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
// .............................................................................
|
||||
// apply consolidation policies
|
||||
// .............................................................................
|
||||
for (auto& entry: state._consolidationPolicies) {
|
||||
if (!entry._intervalStep || ++entry._intervalCount < entry._intervalStep) {
|
||||
continue; // skip if interval not reached or no valid policy to execute
|
||||
}
|
||||
|
||||
entry._intervalCount = 0;
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting consolidation for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
try {
|
||||
SCOPED_LOCK(mutex);
|
||||
|
||||
auto& memoryStore = activeMemoryStore();
|
||||
memoryStore._writer->consolidate(entry._policy, false);
|
||||
|
||||
if (_storePersisted) {
|
||||
_storePersisted._writer->consolidate(entry._policy, false);
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while consolidating iResearch view '" << id() << "': " << e.what();
|
||||
IR_EXCEPTION();
|
||||
} catch (...) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "caught exception while consolidating iResearch view '" << id() << "'";
|
||||
IR_EXCEPTION();
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished consolidation for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// apply data store commit
|
||||
// .............................................................................
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting commit for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
auto res = sync(std::max(size_t(1), size_t(thresholdMsec - TRI_microtime() * 1000))); // set min 1 msec to enable early termination
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished commit for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
// .............................................................................
|
||||
// apply cleanup
|
||||
// .............................................................................
|
||||
if (state._cleanupIntervalStep && ++state._cleanupIntervalCount >= state._cleanupIntervalStep) {
|
||||
state._cleanupIntervalCount = 0;
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "starting cleanup for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
cleanup(std::max(size_t(1), size_t(thresholdMsec - TRI_microtime() * 1000))); // set min 1 msec to enable early termination
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished cleanup for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, iresearch::IResearchFeature::IRESEARCH)
|
||||
<< "finished flush for iResearch view '" << id() << "' run id '" << size_t(&runId) << "'";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*static*/ std::string const& IResearchView::type() noexcept {
|
||||
return VIEW_TYPE;
|
||||
}
|
||||
|
@ -1929,7 +1980,7 @@ arangodb::Result IResearchView::updateProperties(
|
|||
if (index && arangodb::Index::TRI_IDX_TYPE_IRESEARCH_LINK == index->type()) {
|
||||
auto* link = dynamic_cast<arangodb::iresearch::IResearchLink*>(index.get());
|
||||
|
||||
if (link && link->_defaultId == id() && !link->_view->get()) {
|
||||
if (link && link->_defaultId == id() && !link->view()) {
|
||||
arangodb::velocypack::Builder linkBuilder;
|
||||
bool valid;
|
||||
|
||||
|
@ -1996,6 +2047,7 @@ arangodb::Result IResearchView::updateProperties(
|
|||
|
||||
try {
|
||||
storePersisted._reader = irs::directory_reader::open(*(storePersisted._directory));
|
||||
storePersisted._segmentCount += storePersisted._reader.size(); // add commited segments (previously had 0)
|
||||
dropDataPath = _storePersisted ? srcDataPath.c_str() : nullptr;
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, iresearch::IResearchFeature::IRESEARCH)
|
||||
|
|
|
@ -239,6 +239,15 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
IResearchLinkMeta const& meta
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief link the specified 'cid' to the view using the specified 'link'
|
||||
/// definition (!link.isObject() == remove only)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
arangodb::Result link(
|
||||
TRI_voc_cid_t cid,
|
||||
arangodb::velocypack::Slice const link
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief view factory
|
||||
/// @returns initialized view object
|
||||
|
@ -326,6 +335,7 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
struct DataStore {
|
||||
irs::directory::ptr _directory;
|
||||
irs::directory_reader _reader;
|
||||
std::atomic<size_t> _segmentCount{}; // total number of segments in the writer
|
||||
irs::index_writer::ptr _writer;
|
||||
DataStore() = default;
|
||||
DataStore(DataStore&& other) noexcept;
|
||||
|
@ -340,26 +350,6 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
MemoryStore(); // initialize _directory and _writer during allocation
|
||||
};
|
||||
|
||||
struct SyncState {
|
||||
struct PolicyState {
|
||||
size_t _intervalCount;
|
||||
size_t _intervalStep;
|
||||
|
||||
std::shared_ptr<irs::index_writer::consolidation_policy_t> _policy;
|
||||
PolicyState(
|
||||
size_t intervalStep,
|
||||
const std::shared_ptr<irs::index_writer::consolidation_policy_t>& policy
|
||||
);
|
||||
};
|
||||
|
||||
size_t _cleanupIntervalCount;
|
||||
size_t _cleanupIntervalStep;
|
||||
std::vector<PolicyState> _consolidationPolicies;
|
||||
|
||||
SyncState() noexcept;
|
||||
explicit SyncState(IResearchViewMeta::CommitMeta const& meta);
|
||||
};
|
||||
|
||||
struct TidStore {
|
||||
TidStore(
|
||||
transaction::Methods& trx,
|
||||
|
@ -393,14 +383,6 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
arangodb::velocypack::Slice const& info
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief run cleaners on data directories to remove unused files
|
||||
/// @param maxMsec try not to exceed the specified time, casues partial cleanup
|
||||
/// 0 == full cleanup
|
||||
/// @return success
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool cleanup(size_t maxMsec = 0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Called in post-recovery to remove any dangling documents old links
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -411,15 +393,6 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int finish(TRI_voc_tid_t tid, bool commit);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wait for a flush of all index data to its respective stores
|
||||
/// @param meta configuraton to use for sync
|
||||
/// @param maxMsec try not to exceed the specified time, casues partial sync
|
||||
/// 0 == full sync
|
||||
/// @return success
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool sync(SyncState& state, size_t maxMsec = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief registers a callback for flush feature
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -448,4 +421,4 @@ class IResearchView final: public arangodb::ViewImplementation,
|
|||
|
||||
NS_END // iresearch
|
||||
NS_END // arangodb
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -162,13 +162,13 @@ bool initCommitMeta(
|
|||
}
|
||||
|
||||
static const ConsolidationPolicy& defaultPolicy = ConsolidationPolicy::DEFAULT(policyItr->second);
|
||||
size_t intervalStep = 0;
|
||||
size_t segmentThreshold = 0;
|
||||
|
||||
{
|
||||
// optional size_t
|
||||
static const std::string subFieldName("intervalStep");
|
||||
static const std::string subFieldName("segmentThreshold");
|
||||
|
||||
if (!arangodb::iresearch::getNumber(intervalStep, value, subFieldName, tmpSeen, defaultPolicy.intervalStep())) {
|
||||
if (!arangodb::iresearch::getNumber(segmentThreshold, value, subFieldName, tmpSeen, defaultPolicy.segmentThreshold())) {
|
||||
errorField = fieldName + "=>" + name + "=>" + subFieldName;
|
||||
|
||||
return false;
|
||||
|
@ -189,8 +189,8 @@ bool initCommitMeta(
|
|||
}
|
||||
|
||||
// add only enabled policies
|
||||
if (intervalStep) {
|
||||
meta._consolidationPolicies.emplace_back(policyItr->second, intervalStep, threshold);
|
||||
if (segmentThreshold) {
|
||||
meta._consolidationPolicies.emplace_back(policyItr->second, segmentThreshold, threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ bool jsonCommitMeta(
|
|||
arangodb::velocypack::ObjectBuilder subBuilderWrapper(&subBuilder);
|
||||
|
||||
for (auto& policy: meta._consolidationPolicies) {
|
||||
if (!policy.intervalStep()) {
|
||||
if (!policy.segmentThreshold()) {
|
||||
continue; // do not output disabled consolidation policies
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ bool jsonCommitMeta(
|
|||
{
|
||||
arangodb::velocypack::ObjectBuilder policyBuilderWrapper(&policyBuilder);
|
||||
|
||||
policyBuilderWrapper->add("intervalStep", arangodb::velocypack::Value(policy.intervalStep()));
|
||||
policyBuilderWrapper->add("segmentThreshold", arangodb::velocypack::Value(policy.segmentThreshold()));
|
||||
policyBuilderWrapper->add("threshold", arangodb::velocypack::Value(policy.threshold()));
|
||||
}
|
||||
|
||||
|
@ -260,11 +260,11 @@ NS_BEGIN(iresearch)
|
|||
size_t IResearchViewMeta::CommitMeta::ConsolidationPolicy::Hash::operator()(
|
||||
IResearchViewMeta::CommitMeta::ConsolidationPolicy const& value
|
||||
) const {
|
||||
auto step = value.intervalStep();
|
||||
auto segmentThreshold = value.segmentThreshold();
|
||||
auto threshold = value.threshold();
|
||||
auto type = value.type();
|
||||
|
||||
return std::hash<decltype(step)>{}(step)
|
||||
return std::hash<decltype(segmentThreshold)>{}(segmentThreshold)
|
||||
^ std::hash<decltype(threshold)>{}(threshold)
|
||||
^ std::hash<size_t>{}(size_t(type))
|
||||
;
|
||||
|
@ -272,9 +272,9 @@ size_t IResearchViewMeta::CommitMeta::ConsolidationPolicy::Hash::operator()(
|
|||
|
||||
IResearchViewMeta::CommitMeta::ConsolidationPolicy::ConsolidationPolicy(
|
||||
IResearchViewMeta::CommitMeta::ConsolidationPolicy::Type type,
|
||||
size_t intervalStep,
|
||||
size_t segmentThreshold,
|
||||
float threshold
|
||||
): _intervalStep(intervalStep), _threshold(threshold), _type(type) {
|
||||
): _segmentThreshold(segmentThreshold), _threshold(threshold), _type(type) {
|
||||
switch (type) {
|
||||
case Type::BYTES:
|
||||
_policy = irs::index_utils::consolidate_bytes(_threshold);
|
||||
|
@ -311,7 +311,7 @@ IResearchViewMeta::CommitMeta::ConsolidationPolicy& IResearchViewMeta::CommitMet
|
|||
IResearchViewMeta::CommitMeta::ConsolidationPolicy const& other
|
||||
) {
|
||||
if (this != &other) {
|
||||
_intervalStep = other._intervalStep;
|
||||
_segmentThreshold = other._segmentThreshold;
|
||||
_policy = other._policy;
|
||||
_threshold = other._threshold;
|
||||
_type = other._type;
|
||||
|
@ -324,7 +324,7 @@ IResearchViewMeta::CommitMeta::ConsolidationPolicy& IResearchViewMeta::CommitMet
|
|||
IResearchViewMeta::CommitMeta::ConsolidationPolicy&& other
|
||||
) noexcept {
|
||||
if (this != &other) {
|
||||
_intervalStep = std::move(other._intervalStep);
|
||||
_segmentThreshold = std::move(other._segmentThreshold);
|
||||
_policy = std::move(other._policy);
|
||||
_threshold = std::move(other._threshold);
|
||||
_type = std::move(other._type);
|
||||
|
@ -337,7 +337,7 @@ bool IResearchViewMeta::CommitMeta::ConsolidationPolicy::operator==(
|
|||
IResearchViewMeta::CommitMeta::ConsolidationPolicy const& other
|
||||
) const noexcept {
|
||||
return _type == other._type
|
||||
&& _intervalStep == other._intervalStep
|
||||
&& _segmentThreshold == other._segmentThreshold
|
||||
&& _threshold == other._threshold
|
||||
;
|
||||
}
|
||||
|
@ -348,22 +348,22 @@ bool IResearchViewMeta::CommitMeta::ConsolidationPolicy::operator==(
|
|||
switch (type) {
|
||||
case Type::BYTES:
|
||||
{
|
||||
static const ConsolidationPolicy policy(type, 10, 0.85f);
|
||||
static const ConsolidationPolicy policy(type, 300, 0.85f);
|
||||
return policy;
|
||||
}
|
||||
case Type::BYTES_ACCUM:
|
||||
{
|
||||
static const ConsolidationPolicy policy(type, 10, 0.85f);
|
||||
static const ConsolidationPolicy policy(type, 300, 0.85f);
|
||||
return policy;
|
||||
}
|
||||
case Type::COUNT:
|
||||
{
|
||||
static const ConsolidationPolicy policy(type, 10, 0.85f);
|
||||
static const ConsolidationPolicy policy(type, 300, 0.85f);
|
||||
return policy;
|
||||
}
|
||||
case Type::FILL:
|
||||
{
|
||||
static const ConsolidationPolicy policy(type, 10, 0.85f);
|
||||
static const ConsolidationPolicy policy(type, 300, 0.85f);
|
||||
return policy;
|
||||
}
|
||||
default:
|
||||
|
@ -373,8 +373,8 @@ bool IResearchViewMeta::CommitMeta::ConsolidationPolicy::operator==(
|
|||
}
|
||||
}
|
||||
|
||||
size_t IResearchViewMeta::CommitMeta::ConsolidationPolicy::intervalStep() const noexcept {
|
||||
return _intervalStep;
|
||||
size_t IResearchViewMeta::CommitMeta::ConsolidationPolicy::segmentThreshold() const noexcept {
|
||||
return _segmentThreshold;
|
||||
}
|
||||
|
||||
irs::index_writer::consolidation_policy_t const& IResearchViewMeta::CommitMeta::ConsolidationPolicy::policy() const noexcept {
|
||||
|
|
|
@ -74,21 +74,21 @@ struct IResearchViewMeta {
|
|||
FILL, // {threshold} > #segment_docs{valid} / (#segment_docs{valid} + #segment_docs{removed})
|
||||
};
|
||||
|
||||
ConsolidationPolicy(Type type, size_t intervalStep, float threshold);
|
||||
ConsolidationPolicy(Type type, size_t segmentThreshold, float threshold);
|
||||
ConsolidationPolicy(ConsolidationPolicy const& other);
|
||||
ConsolidationPolicy(ConsolidationPolicy&& other) noexcept;
|
||||
ConsolidationPolicy& operator=(ConsolidationPolicy const& other);
|
||||
ConsolidationPolicy& operator=(ConsolidationPolicy&& other) noexcept;
|
||||
bool operator==(ConsolidationPolicy const& other) const noexcept;
|
||||
static const ConsolidationPolicy& DEFAULT(Type type); // default values for a given type
|
||||
size_t intervalStep() const noexcept;
|
||||
irs::index_writer::consolidation_policy_t const& policy() const noexcept;
|
||||
size_t segmentThreshold() const noexcept;
|
||||
float threshold() const noexcept;
|
||||
Type type() const noexcept;
|
||||
|
||||
private:
|
||||
size_t _intervalStep; // apply consolidation policy with every Nth commit (0 == disable)
|
||||
irs::index_writer::consolidation_policy_t _policy;
|
||||
size_t _segmentThreshold; // apply policy if number of segments is >= value (0 == disable)
|
||||
float _threshold; // consolidation policy threshold
|
||||
Type _type;
|
||||
};
|
||||
|
|
|
@ -93,22 +93,22 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertTrue(Object === properties.commit.consolidate.constructor);
|
||||
assertEqual(4, Object.keys(properties.commit.consolidate).length);
|
||||
assertTrue(Object === properties.commit.consolidate.bytes.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertTrue(Object === properties.commit.consolidate.bytes_accum.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertTrue(Object === properties.commit.consolidate.count.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertTrue(Object === properties.commit.consolidate.fill.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.fill.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.fill.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.fill.threshold.toFixed(6));
|
||||
|
||||
meta = { commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -122,18 +122,18 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertTrue(Object === properties.commit.consolidate.constructor);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertTrue(Object === properties.commit.consolidate.bytes.constructor);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertTrue(Object === properties.commit.consolidate.bytes_accum.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertTrue(Object === properties.commit.consolidate.count.constructor);
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
|
||||
meta = { commit: {
|
||||
cleanupIntervalStep: 20,
|
||||
consolidate: { count: { intervalStep: 30, threshold: 0.75 } }
|
||||
consolidate: { count: { segmentThreshold: 30, threshold: 0.75 } }
|
||||
} };
|
||||
view.properties(meta, false); // full update
|
||||
properties = view.properties();
|
||||
|
@ -144,7 +144,7 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertTrue(Object === properties.commit.consolidate.constructor);
|
||||
assertEqual(1, Object.keys(properties.commit.consolidate).length);
|
||||
assertTrue(Object === properties.commit.consolidate.count.constructor);
|
||||
assertEqual(30, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(30, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.75).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
|
||||
|
||||
|
@ -465,7 +465,7 @@ function iResearchFeatureAqlTestSuite () {
|
|||
commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -484,11 +484,11 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertEqual(10000, properties.commit.commitIntervalMsec);
|
||||
assertEqual(5000, properties.commit.commitTimeoutMsec);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertEqual("TestPath", properties.dataPath);
|
||||
assertEqual("de_DE.UTF-8", properties.locale);
|
||||
|
@ -518,7 +518,7 @@ function iResearchFeatureAqlTestSuite () {
|
|||
commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -541,11 +541,11 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertEqual(10000, properties.commit.commitIntervalMsec);
|
||||
assertEqual(5000, properties.commit.commitTimeoutMsec);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertEqual("TestPath", properties.dataPath);
|
||||
assertEqual("de_DE.UTF-8", properties.locale);
|
||||
|
@ -575,7 +575,7 @@ function iResearchFeatureAqlTestSuite () {
|
|||
commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -598,11 +598,11 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertEqual(10000, properties.commit.commitIntervalMsec);
|
||||
assertEqual(5000, properties.commit.commitTimeoutMsec);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertEqual("TestPath", properties.dataPath);
|
||||
assertEqual("de_DE.UTF-8", properties.locale);
|
||||
|
@ -635,7 +635,7 @@ function iResearchFeatureAqlTestSuite () {
|
|||
commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -658,11 +658,11 @@ function iResearchFeatureAqlTestSuite () {
|
|||
assertEqual(10000, properties.commit.commitIntervalMsec);
|
||||
assertEqual(5000, properties.commit.commitTimeoutMsec);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertEqual("TestPath", properties.dataPath);
|
||||
assertEqual("de_DE.UTF-8", properties.locale);
|
||||
|
|
|
@ -298,10 +298,15 @@ function iResearchAqlTestSuite () {
|
|||
// },
|
||||
|
||||
testPhraseFilter : function () {
|
||||
var result = AQL_EXECUTE("FOR doc IN VIEW UnitTestsView FILTER PHRASE(doc.text, 'quick brown fox jumps', 'text_en') RETURN doc", null, { waitForSync: true }).json;
|
||||
var result0 = AQL_EXECUTE("FOR doc IN VIEW UnitTestsView FILTER PHRASE(doc.text, 'quick brown fox jumps', 'text_en') RETURN doc", null, { waitForSync: true }).json;
|
||||
|
||||
assertEqual(result.length, 1);
|
||||
assertEqual(result[0].name, 'full');
|
||||
assertEqual(result0.length, 1);
|
||||
assertEqual(result0[0].name, 'full');
|
||||
|
||||
var result1 = AQL_EXECUTE("FOR doc IN VIEW UnitTestsView FILTER PHRASE(doc.text, [ 'quick brown fox jumps' ], 'text_en') RETURN doc", null, { waitForSync: true }).json;
|
||||
|
||||
assertEqual(result1.length, 1);
|
||||
assertEqual(result1[0].name, 'full');
|
||||
},
|
||||
|
||||
testExistsFilter : function () {
|
||||
|
|
|
@ -75,9 +75,8 @@ function recoverySuite () {
|
|||
assertTrue(p.hasOwnProperty('UnitTestsRecoveryDummy'));
|
||||
assertTrue(p.UnitTestsRecoveryDummy.includeAllFields);
|
||||
|
||||
// FIXME uncomment when rocksdb recovery will be fixed
|
||||
// var result = AQL_EXECUTE("FOR doc IN VIEW UnitTestsRecoveryView FILTER doc.c >= 0 COLLECT WITH COUNT INTO length RETURN length", null, { }).json;
|
||||
// assertEqual(result[0], 10000);
|
||||
var result = AQL_EXECUTE("FOR doc IN VIEW UnitTestsRecoveryView FILTER doc.c >= 0 COLLECT WITH COUNT INTO length RETURN length", null, { }).json;
|
||||
assertEqual(result[0], 10000);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ function runSetup () {
|
|||
commit: {
|
||||
commitIntervalMsec: 10000,
|
||||
consolidate: {
|
||||
bytes: { intervalStep: 20, threshold: 0.5 },
|
||||
bytes: { segmentThreshold: 20, threshold: 0.5 },
|
||||
bytes_accum: {},
|
||||
count: {}
|
||||
}
|
||||
|
@ -91,9 +91,8 @@ function recoverySuite () {
|
|||
assertTrue(p.hasOwnProperty('UnitTestsRecoveryDummy'));
|
||||
assertTrue(p.UnitTestsRecoveryDummy.includeAllFields);
|
||||
|
||||
// uncomment when rocksdb recovery will be fixed
|
||||
// var result = AQL_EXECUTE("FOR doc IN VIEW UnitTestsRecoveryView FILTER doc.c >= 0 COLLECT WITH COUNT INTO length RETURN length", null, { }).json;
|
||||
// assertEqual(result[0], 10000);
|
||||
var result = AQL_EXECUTE("FOR doc IN VIEW UnitTestsRecoveryView FILTER doc.c >= 0 COLLECT WITH COUNT INTO length RETURN length", null, { }).json;
|
||||
assertEqual(result[0], 10000);
|
||||
|
||||
// validate state
|
||||
var properties = v.properties();
|
||||
|
@ -101,11 +100,11 @@ function recoverySuite () {
|
|||
assertEqual(10000, properties.commit.commitIntervalMsec);
|
||||
assertEqual(5000, properties.commit.commitTimeoutMsec);
|
||||
assertEqual(3, Object.keys(properties.commit.consolidate).length);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.intervalStep);
|
||||
assertEqual(20, properties.commit.consolidate.bytes.segmentThreshold);
|
||||
assertEqual((0.5).toFixed(6), properties.commit.consolidate.bytes.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.bytes_accum.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.bytes_accum.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.bytes_accum.threshold.toFixed(6));
|
||||
assertEqual(10, properties.commit.consolidate.count.intervalStep);
|
||||
assertEqual(300, properties.commit.consolidate.count.segmentThreshold);
|
||||
assertEqual((0.85).toFixed(6), properties.commit.consolidate.count.threshold.toFixed(6));
|
||||
assertEqual("TestPath", properties.dataPath);
|
||||
assertEqual("de_DE.UTF-8", properties.locale);
|
||||
|
|
|
@ -38,6 +38,8 @@ if [ -z "${ARANGOSH}" ]; then
|
|||
ARANGOSH="build/bin/arangosh${EXT}"
|
||||
elif [ -x bin/arangosh ]; then
|
||||
ARANGOSH="bin/arangosh${EXT}"
|
||||
elif [ -x arangosh ]; then
|
||||
ARANGOSH="arangosh${EXT}"
|
||||
elif [ -x usr/bin/arangosh ]; then
|
||||
ARANGOSH="usr/bin/arangosh${EXT}"
|
||||
else
|
||||
|
|
|
@ -1248,6 +1248,8 @@ SECTION("Phrase") {
|
|||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(false, 'quick', 'test_analyzer') RETURN d");
|
||||
|
||||
// invalid input
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 1, \"abc\" ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 1, \"abc\" ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, true, 'test_analyzer') RETURN d");
|
||||
|
@ -1318,6 +1320,7 @@ SECTION("Phrase") {
|
|||
phrase.push_back("q").push_back("u").push_back("i").push_back("c").push_back("k");
|
||||
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[42], 'quick', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[42], [ 'quick' ], 'test_analyzer') RETURN d", expected);
|
||||
}
|
||||
|
||||
// without offset, custom analyzer, expressions
|
||||
|
@ -1334,8 +1337,12 @@ SECTION("Phrase") {
|
|||
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d.name, CONCAT(value,'ck'), CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d['name'], CONCAT(value, 'ck'), CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d.name, [ CONCAT(value,'ck') ], CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d['name'], [ CONCAT(value, 'ck') ], CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d.name, CONCAT(value, 'ck'), CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d['name'], CONCAT(value, 'ck'), CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d.name, [ CONCAT(value, 'ck') ], CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d['name'], [ CONCAT(value, 'ck') ], CONCAT(analyzer, 'analyzer')) RETURN d", expected, &ctx);
|
||||
}
|
||||
|
||||
// without offset, custom analyzer, invalid expressions
|
||||
|
@ -1347,8 +1354,12 @@ SECTION("Phrase") {
|
|||
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d.name, CONCAT(value,'ck'), analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d['name'], CONCAT(value, 'ck'), analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d.name, [ CONCAT(value,'ck') ], analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phrase(d['name'], [ CONCAT(value, 'ck') ], analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d.name, CONCAT(value, 'ck'), analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d['name'], CONCAT(value, 'ck'), analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d.name, [ CONCAT(value, 'ck') ], analyzer) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET value='qui' LET analyzer='test_' FOR d IN VIEW myView FILTER phRase(d['name'], [ CONCAT(value, 'ck') ], analyzer) RETURN d", &ctx);
|
||||
}
|
||||
|
||||
// with offset, custom analyzer
|
||||
|
@ -1363,6 +1374,9 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 0, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 0.0, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 0.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 0.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 0.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
|
||||
// wrong offset argument
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', '0', 'brown', 'test_analyzer') RETURN d");
|
||||
|
@ -1370,6 +1384,11 @@ SECTION("Phrase") {
|
|||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', true, 'brown', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', false, 'brown', 'test_analyzer') RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', d.name, 'brown', 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', '0', 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', null, 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', true, 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', false, 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', d.name, 'brown' ], 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
}
|
||||
|
||||
// with offset, complex name, custom analyzer
|
||||
|
@ -1387,6 +1406,12 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj['name'], 'quick', 5.0, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.name, 'quick', 5.6, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj']['name'], 'quick', 5.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj']['name'], [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.name, [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.name, [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj['name'], [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.name, [ 'quick', 5.6, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj']['name'], [ 'quick', 5.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
}
|
||||
|
||||
// with offset, complex name with offset, custom analyzer
|
||||
|
@ -1404,6 +1429,12 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3]['name'][1], 'quick', 5.0, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3].name[1], 'quick', 5.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj'][3]['name'][1], 'quick', 5.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj'][3].name[1], [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3].name[1], [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3].name[1], [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3]['name'][1], [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj[3].name[1], [ 'quick', 5.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj'][3]['name'][1], [ 'quick', 5.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
}
|
||||
|
||||
// with offset, complex name, custom analyzer
|
||||
|
@ -1421,6 +1452,12 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj['name'][100], 'quick', 5.0, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj.name[100], 'quick', 5.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5]['obj']['name'][100], 'quick', 5.5, 'brown', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5]['obj'].name[100], [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj.name[100], [ 'quick', 5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj.name[100], [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj['name'][100], [ 'quick', 5.0, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5].obj.name[100], [ 'quick', 5.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d[5]['obj']['name'][100], [ 'quick', 5.5, 'brown' ], 'test_analyzer') RETURN d", expected);
|
||||
}
|
||||
|
||||
// multiple offsets, complex name, custom analyzer
|
||||
|
@ -1443,6 +1480,15 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', 2.5, 'fox', 0.0, 'jumps', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3.2, 'brown', 2.0, 'fox', 0.0, 'jumps', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj']['properties']['id']['name'], 'quick', 3.2, 'brown', 2.0, 'fox', 0.0, 'jumps', 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3.0, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id['name'], [ 'quick', 3.0, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3.6, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj['properties'].id.name, [ 'quick', 3.6, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', 2.0, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', 2.5, 'fox', 0.0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3.2, 'brown', 2.0, 'fox', 0.0, 'jumps' ], 'test_analyzer') RETURN d", expected);
|
||||
assertFilterSuccess("FOR d IN VIEW myView FILTER phrase(d['obj']['properties']['id']['name'], [ 'quick', 3.2, 'brown', 2.0, 'fox', 0.0, 'jumps'] , 'test_analyzer') RETURN d", expected);
|
||||
|
||||
// wrong value
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, d.brown, 2, 'fox', 0, 'jumps', 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
|
@ -1452,12 +1498,23 @@ SECTION("Phrase") {
|
|||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, true, 2, 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, false, 2, 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', 2, 'fox', 0, d, 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, d.brown, 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 2, 2, 'fox', 0, 'jumps'] , 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 2.5, 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, null, 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, true, 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, false, 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', 2, 'fox', 0, d ], 'test_analyzer') RETURN d", &ExpressionContextMock::EMPTY);
|
||||
|
||||
// wrong offset argument
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', '2', 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', null, 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', true, 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', false, 'fox', 0, 'jumps', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', '2', 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', null, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', true, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', false, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d");
|
||||
}
|
||||
|
||||
// multiple offsets, complex name, custom analyzer, expressions
|
||||
|
@ -1481,6 +1538,12 @@ SECTION("Phrase") {
|
|||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3.6, 'brown', 2, 'fox', offset-2, 'jumps', 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj['properties'].id.name, 'quick', 3.6, CONCAT(input, 'wn'), 2, 'fox', 0, 'jumps', 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', 3, 'brown', offset+0.5, 'fox', 0.0, 'jumps', 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', offset+1, CONCAT(input, 'wn'), offset, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', offset + 1.5, 'brown', 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id['name'], [ 'quick', 3.0, 'brown', offset, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3.6, 'brown', 2, 'fox', offset-2, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj['properties'].id.name, [ 'quick', 3.6, CONCAT(input, 'wn'), 2, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
assertFilterSuccess("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', 3, 'brown', offset+0.5, 'fox', 0.0, 'jumps' ], 'test_analyzer') RETURN d", expected, &ctx);
|
||||
}
|
||||
|
||||
// multiple offsets, complex name, custom analyzer, invalid expressions
|
||||
|
@ -1494,6 +1557,10 @@ SECTION("Phrase") {
|
|||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', offset + 1.5, 'brown', TO_STRING(2), 'fox', 0, 'jumps', 'test_analyzer') RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id['name'], 'quick', 3.0, 'brown', offset, 'fox', 0, 'jumps', TO_BOOL('test_analyzer')) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, 'quick', TO_BOOL(3.6), 'brown', 2, 'fox', offset-2, 'jumps', 'test_analyzer') RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', TO_BOOL(offset+1), CONCAT(input, 'wn'), offset, 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', offset + 1.5, 'brown', TO_STRING(2), 'fox', 0, 'jumps' ], 'test_analyzer') RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id['name'], [ 'quick', 3.0, 'brown', offset, 'fox', 0, 'jumps' ], TO_BOOL('test_analyzer')) RETURN d", &ctx);
|
||||
assertFilterExecutionFail("LET offset=2 LET input='bro' FOR d IN VIEW myView FILTER phrase(d.obj.properties.id.name, [ 'quick', TO_BOOL(3.6), 'brown', 2, 'fox', offset-2, 'jumps' ], 'test_analyzer') RETURN d", &ctx);
|
||||
}
|
||||
|
||||
// invalid analyzer
|
||||
|
@ -1509,6 +1576,18 @@ SECTION("Phrase") {
|
|||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], 'quick', { \"a\": 7, \"b\": \"c\" }) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 'invalid_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], 'quick', 'invalid_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], [ 1, \"abc\" ]) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], [ 1, \"abc\" ]) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], true) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], false) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], null) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], null) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], 3.14) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], 1234) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], { \"a\": 7, \"b\": \"c\" }) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], { \"a\": 7, \"b\": \"c\" }) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], 'invalid_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d['name'], [ 'quick' ], 'invalid_analyzer') RETURN d");
|
||||
|
||||
// wrong analylzer
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', ['d']) RETURN d");
|
||||
|
@ -1527,12 +1606,32 @@ SECTION("Phrase") {
|
|||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 3, 'brown', false) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 3, 'brown', null) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 3, 'brown', 'invalidAnalyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], ['d']) RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], [d]) RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], d) RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], 3) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], 3.0) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], true) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], false) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], null) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick' ], 'invalidAnalyzer') RETURN d");
|
||||
assertFilterExecutionFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], d) RETURN d", &ExpressionContextMock::EMPTY);
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], 3) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], 3.0) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], true) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], false) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], null) RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 3, 'brown' ], 'invalidAnalyzer') RETURN d");
|
||||
|
||||
// non-deterministic arguments
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d[RAND() ? 'name' : 0], 'quick', 0, 'brown', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, RAND() ? 'quick' : 'slow', 0, 'brown', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 0, RAND() ? 'brown' : 'red', 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, 'quick', 0, 'brown', RAND() ? 'test_analyzer' : 'invalid_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d[RAND() ? 'name' : 0], [ 'quick', 0, 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ RAND() ? 'quick' : 'slow', 0, 'brown' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 0, RAND() ? 'brown' : 'red' ], 'test_analyzer') RETURN d");
|
||||
assertFilterFail("FOR d IN VIEW myView FILTER phrase(d.name, [ 'quick', 0, 'brown' ], RAND() ? 'test_analyzer' : 'invalid_analyzer') RETURN d");
|
||||
}
|
||||
|
||||
SECTION("StartsWith") {
|
||||
|
|
|
@ -422,6 +422,24 @@ TEST_CASE("IResearchQueryTestPhrase", "[iresearch][iresearch-query]") {
|
|||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test invalid input type (empty-array)
|
||||
{
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d.value, [ ], 'identity') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_QUERY_PARSE == result.code);
|
||||
}
|
||||
|
||||
// test invalid input type (empty-array) via []
|
||||
{
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d['value'], [ ], 'identity') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_QUERY_PARSE == result.code);
|
||||
}
|
||||
|
||||
// test invalid input type (array)
|
||||
{
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
|
@ -797,6 +815,166 @@ TEST_CASE("IResearchQueryTestPhrase", "[iresearch][iresearch-query]") {
|
|||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
insertedDocs[7].slice(),
|
||||
insertedDocs[8].slice(),
|
||||
insertedDocs[13].slice(),
|
||||
insertedDocs[19].slice(),
|
||||
insertedDocs[22].slice(),
|
||||
insertedDocs[24].slice(),
|
||||
insertedDocs[29].slice(),
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d.duplicated, [ 'z' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer via [] with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
insertedDocs[7].slice(),
|
||||
insertedDocs[8].slice(),
|
||||
insertedDocs[13].slice(),
|
||||
insertedDocs[19].slice(),
|
||||
insertedDocs[22].slice(),
|
||||
insertedDocs[24].slice(),
|
||||
insertedDocs[29].slice(),
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d['duplicated'], [ 'z' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer with offsets with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
insertedDocs[7].slice(),
|
||||
insertedDocs[8].slice(),
|
||||
insertedDocs[13].slice(),
|
||||
insertedDocs[19].slice(),
|
||||
insertedDocs[22].slice(),
|
||||
insertedDocs[24].slice(),
|
||||
insertedDocs[29].slice(),
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d.duplicated, [ 'v', 1, 'z' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer with offsets via [] with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
insertedDocs[7].slice(),
|
||||
insertedDocs[8].slice(),
|
||||
insertedDocs[13].slice(),
|
||||
insertedDocs[19].slice(),
|
||||
insertedDocs[22].slice(),
|
||||
insertedDocs[24].slice(),
|
||||
insertedDocs[29].slice(),
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d['duplicated'], [ 'v', 2, 'c' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer with offsets (no match) with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d.duplicated, [ 'v', 0, 'z' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
|
||||
// test custom analyzer with offsets (no match) via [] with [ phrase ] arg
|
||||
{
|
||||
std::vector<arangodb::velocypack::Slice> expected = {
|
||||
};
|
||||
auto result = arangodb::tests::executeQuery(
|
||||
vocbase,
|
||||
"FOR d IN VIEW testView FILTER PHRASE(d['duplicated'], [ 'v', 1, 'c' ], 'test_analyzer') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"
|
||||
);
|
||||
REQUIRE(TRI_ERROR_NO_ERROR == result.code);
|
||||
auto slice = result.result->slice();
|
||||
CHECK(slice.isArray());
|
||||
size_t i = 0;
|
||||
|
||||
for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) {
|
||||
auto const resolved = itr.value().resolveExternals();
|
||||
CHECK((i < expected.size()));
|
||||
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], resolved, true)));
|
||||
}
|
||||
|
||||
CHECK((i == expected.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -778,6 +778,251 @@ SECTION("test_insert") {
|
|||
}
|
||||
}
|
||||
|
||||
SECTION("test_link") {
|
||||
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testCollection\", \"id\": 100 }");
|
||||
auto viewJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testView\", \"type\": \"arangosearch\" }");
|
||||
|
||||
// drop invalid collection
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((true == viewImpl->link(100, arangodb::velocypack::Slice::nullSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// drop non-exiting
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto* logicalCollection = vocbase.createCollection(collectionJson->slice());
|
||||
CHECK((nullptr != logicalCollection));
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((true == viewImpl->link(logicalCollection->cid(), arangodb::velocypack::Slice::nullSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// drop exiting
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto* logicalCollection = vocbase.createCollection(collectionJson->slice());
|
||||
CHECK((nullptr != logicalCollection));
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
auto links = arangodb::velocypack::Parser::fromJson("{ \
|
||||
\"links\": { \"testCollection\": {} } \
|
||||
}");
|
||||
CHECK((true == logicalView->updateProperties(links->slice(), true, false).ok()));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((1 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((true == viewImpl->link(logicalCollection->cid(), arangodb::velocypack::Slice::nullSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
CHECK((true == logicalCollection->getIndexes().empty()));
|
||||
}
|
||||
}
|
||||
|
||||
// drop invalid collection + recreate
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((false == viewImpl->link(100, arangodb::iresearch::emptyObjectSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// drop non-existing + recreate
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto* logicalCollection = vocbase.createCollection(collectionJson->slice());
|
||||
CHECK((nullptr != logicalCollection));
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((0 == cids.size()));
|
||||
CHECK((true == logicalCollection->getIndexes().empty()));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((true == viewImpl->link(logicalCollection->cid(), arangodb::iresearch::emptyObjectSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
std::unordered_set<TRI_voc_cid_t> expected = { 100 };
|
||||
|
||||
for (auto& cid: expected) {
|
||||
CHECK((1 == cids.erase(cid)));
|
||||
}
|
||||
|
||||
CHECK((0 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
}
|
||||
}
|
||||
|
||||
// drop existing + recreate
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto* logicalCollection = vocbase.createCollection(collectionJson->slice());
|
||||
CHECK((nullptr != logicalCollection));
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
auto links = arangodb::velocypack::Parser::fromJson("{ \
|
||||
\"links\": { \"testCollection\": { \"includeAllFields\": true } } \
|
||||
}");
|
||||
CHECK((true == logicalView->updateProperties(links->slice(), true, false).ok()));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((1 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
auto link = logicalCollection->getIndexes()[0]->toVelocyPack(true, false);
|
||||
arangodb::iresearch::IResearchLinkMeta linkMeta;
|
||||
std::string error;
|
||||
CHECK((linkMeta.init(link->slice(), error) && true == linkMeta._includeAllFields));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK((true == viewImpl->link(logicalCollection->cid(), arangodb::iresearch::emptyObjectSlice()).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
std::unordered_set<TRI_voc_cid_t> expected = { 100 };
|
||||
|
||||
for (auto& cid: expected) {
|
||||
CHECK((1 == cids.erase(cid)));
|
||||
}
|
||||
|
||||
CHECK((0 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
auto link = logicalCollection->getIndexes()[0]->toVelocyPack(true, false);
|
||||
arangodb::iresearch::IResearchLinkMeta linkMeta;
|
||||
std::string error;
|
||||
CHECK((linkMeta.init(link->slice(), error) && false == linkMeta._includeAllFields));
|
||||
}
|
||||
}
|
||||
|
||||
// drop existing + recreate invalid
|
||||
{
|
||||
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
|
||||
auto* logicalCollection = vocbase.createCollection(collectionJson->slice());
|
||||
CHECK((nullptr != logicalCollection));
|
||||
auto logicalView = vocbase.createView(viewJson->slice(), 0);
|
||||
REQUIRE((false == !logicalView));
|
||||
auto* view = logicalView->getImplementation();
|
||||
REQUIRE((false == !view));
|
||||
auto* viewImpl = dynamic_cast<arangodb::iresearch::IResearchView*>(view);
|
||||
REQUIRE((nullptr != viewImpl));
|
||||
|
||||
auto links = arangodb::velocypack::Parser::fromJson("{ \
|
||||
\"links\": { \"testCollection\": { \"includeAllFields\": true } } \
|
||||
}");
|
||||
CHECK((true == logicalView->updateProperties(links->slice(), true, false).ok()));
|
||||
|
||||
{
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
CHECK((1 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
auto link = logicalCollection->getIndexes()[0]->toVelocyPack(true, false);
|
||||
arangodb::iresearch::IResearchLinkMeta linkMeta;
|
||||
std::string error;
|
||||
CHECK((linkMeta.init(link->slice(), error) && true == linkMeta._includeAllFields));
|
||||
}
|
||||
|
||||
{
|
||||
arangodb::velocypack::Builder builder;
|
||||
builder.openObject();
|
||||
builder.add("includeAllFields", arangodb::velocypack::Value("abc"));
|
||||
builder.close();
|
||||
auto slice = builder.slice();
|
||||
CHECK((false == viewImpl->link(logicalCollection->cid(), slice).ok()));
|
||||
std::set<TRI_voc_cid_t> cids;
|
||||
viewImpl->visitCollections([&cids](TRI_voc_cid_t cid)->bool { cids.emplace(cid); return true; });
|
||||
std::unordered_set<TRI_voc_cid_t> expected = { 100 };
|
||||
|
||||
for (auto& cid: expected) {
|
||||
CHECK((1 == cids.erase(cid)));
|
||||
}
|
||||
|
||||
CHECK((0 == cids.size()));
|
||||
CHECK((1 == logicalCollection->getIndexes().size()));
|
||||
auto link = logicalCollection->getIndexes()[0]->toVelocyPack(true, false);
|
||||
arangodb::iresearch::IResearchLinkMeta linkMeta;
|
||||
std::string error;
|
||||
CHECK((linkMeta.init(link->slice(), error) && true == linkMeta._includeAllFields));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("test_move_datapath") {
|
||||
std::string createDataPath = ((irs::utf8_path()/=s.testFilesystemPath)/=std::string("deleteme0")).utf8();
|
||||
std::string updateDataPath = ((irs::utf8_path()/=s.testFilesystemPath)/=std::string("deleteme1")).utf8();
|
||||
|
@ -1403,6 +1648,7 @@ SECTION("test_unregister_link") {
|
|||
CHECK((1 == cids.size()));
|
||||
|
||||
auto factory = [](arangodb::LogicalView*, arangodb::velocypack::Slice const&, bool isNew)->std::unique_ptr<arangodb::ViewImplementation>{ return nullptr; };
|
||||
logicalCollection->getIndexes()[0]->unload(); // release view reference to prevent deadlock due to ~IResearchView() waiting for IResearchLink::unload()
|
||||
logicalView->spawnImplementation(factory, createJson->slice(), true); // ensure destructor for ViewImplementation is called
|
||||
CHECK((false == logicalCollection->getIndexes().empty()));
|
||||
}
|
||||
|
@ -1494,6 +1740,7 @@ SECTION("test_tracked_cids") {
|
|||
}
|
||||
|
||||
CHECK((expected.empty()));
|
||||
logicalCollection->getIndexes()[0]->unload(); // release view reference to prevent deadlock due to ~IResearchView() waiting for IResearchLink::unload()
|
||||
}
|
||||
|
||||
// test drop via link before open (TRI_vocbase_t::createView(...) will call open())
|
||||
|
@ -2785,4 +3032,4 @@ SECTION("test_update_partial") {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
|
@ -74,7 +74,7 @@ SECTION("test_defaults") {
|
|||
|
||||
for (auto& entry: meta._commit._consolidationPolicies) {
|
||||
CHECK(true == (1 == expectedItem.erase(entry.type())));
|
||||
CHECK(true == (10 == entry.intervalStep()));
|
||||
CHECK(true == (300 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (0.85f == entry.threshold()));
|
||||
}
|
||||
|
@ -123,22 +123,22 @@ SECTION("test_inheritDefaults") {
|
|||
|
||||
switch(entry.type()) {
|
||||
case ConsolidationPolicy::Type::BYTES:
|
||||
CHECK(true == (101 == entry.intervalStep()));
|
||||
CHECK(true == (101 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.11f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::BYTES_ACCUM:
|
||||
CHECK(true == (151 == entry.intervalStep()));
|
||||
CHECK(true == (151 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.151f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::COUNT:
|
||||
CHECK(true == (201 == entry.intervalStep()));
|
||||
CHECK(true == (201 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.21f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::FILL:
|
||||
CHECK(true == (301 == entry.intervalStep()));
|
||||
CHECK(true == (301 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.31f == entry.threshold()));
|
||||
break;
|
||||
|
@ -171,7 +171,7 @@ SECTION("test_readDefaults") {
|
|||
|
||||
for (auto& entry: meta._commit._consolidationPolicies) {
|
||||
CHECK(true == (1 == expectedItem.erase(entry.type())));
|
||||
CHECK(true == (10 == entry.intervalStep()));
|
||||
CHECK(true == (300 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.85f == entry.threshold()));
|
||||
}
|
||||
|
@ -244,9 +244,9 @@ SECTION("test_readCustomizedValues") {
|
|||
|
||||
{
|
||||
std::string errorField;
|
||||
auto json = arangodb::velocypack::Parser::fromJson("{ \"commit\": { \"consolidate\": { \"bytes\": { \"intervalStep\": 0.5, \"threshold\": 1 } } } }");
|
||||
auto json = arangodb::velocypack::Parser::fromJson("{ \"commit\": { \"consolidate\": { \"bytes\": { \"segmentThreshold\": 0.5, \"threshold\": 1 } } } }");
|
||||
CHECK(false == meta.init(json->slice(), errorField, logicalView));
|
||||
CHECK(std::string("commit=>consolidate=>bytes=>intervalStep") == errorField);
|
||||
CHECK(std::string("commit=>consolidate=>bytes=>segmentThreshold") == errorField);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -302,7 +302,7 @@ SECTION("test_readCustomizedValues") {
|
|||
{
|
||||
std::string errorField;
|
||||
auto json = arangodb::velocypack::Parser::fromJson("{ \
|
||||
\"commit\": { \"consolidate\": { \"bytes_accum\": { \"intervalStep\": 0, \"threshold\": 0.2 }, \"fill\": { \"intervalStep\": 0 } } } \
|
||||
\"commit\": { \"consolidate\": { \"bytes_accum\": { \"segmentThreshold\": 0, \"threshold\": 0.2 }, \"fill\": { \"segmentThreshold\": 0 } } } \
|
||||
}");
|
||||
CHECK(true == meta.init(json->slice(), errorField, logicalView));
|
||||
CHECK(true == (meta._commit._consolidationPolicies.empty()));
|
||||
|
@ -312,7 +312,7 @@ SECTION("test_readCustomizedValues") {
|
|||
std::string errorField;
|
||||
auto json = arangodb::velocypack::Parser::fromJson("{ \
|
||||
\"collections\": [ 42 ], \
|
||||
\"commit\": { \"commitIntervalMsec\": 456, \"cleanupIntervalStep\": 654, \"commitTimeoutMsec\": 789, \"consolidate\": { \"bytes\": { \"intervalStep\": 1001, \"threshold\": 0.11 }, \"bytes_accum\": { \"intervalStep\": 1501, \"threshold\": 0.151 }, \"count\": { \"intervalStep\": 2001 }, \"fill\": {} } }, \
|
||||
\"commit\": { \"commitIntervalMsec\": 456, \"cleanupIntervalStep\": 654, \"commitTimeoutMsec\": 789, \"consolidate\": { \"bytes\": { \"segmentThreshold\": 1001, \"threshold\": 0.11 }, \"bytes_accum\": { \"segmentThreshold\": 1501, \"threshold\": 0.151 }, \"count\": { \"segmentThreshold\": 2001 }, \"fill\": {} } }, \
|
||||
\"dataPath\": \"somepath\", \
|
||||
\"locale\": \"ru_RU.KOI8-R\", \
|
||||
\"threadsMaxIdle\": 8, \
|
||||
|
@ -338,22 +338,22 @@ SECTION("test_readCustomizedValues") {
|
|||
|
||||
switch(entry.type()) {
|
||||
case ConsolidationPolicy::Type::BYTES:
|
||||
CHECK(true == (1001 == entry.intervalStep()));
|
||||
CHECK(true == (1001 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.11f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::BYTES_ACCUM:
|
||||
CHECK(true == (1501 == entry.intervalStep()));
|
||||
CHECK(true == (1501 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.151f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::COUNT:
|
||||
CHECK(true == (2001 == entry.intervalStep()));
|
||||
CHECK(true == (2001 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.85f == entry.threshold()));
|
||||
break;
|
||||
case ConsolidationPolicy::Type::FILL:
|
||||
CHECK(true == (10 == entry.intervalStep()));
|
||||
CHECK(true == (300 == entry.segmentThreshold()));
|
||||
CHECK(true == (false == !entry.policy()));
|
||||
CHECK(true == (.85f == entry.threshold()));
|
||||
break;
|
||||
|
@ -369,10 +369,10 @@ SECTION("test_readCustomizedValues") {
|
|||
|
||||
SECTION("test_writeDefaults") {
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, double>> expectedCommitItemConsolidate = {
|
||||
{ "bytes",{ { "intervalStep", 10 },{ "threshold", .85f } } },
|
||||
{ "bytes_accum",{ { "intervalStep", 10 },{ "threshold", .85f } } },
|
||||
{ "count",{ { "intervalStep", 10 },{ "threshold", .85f } } },
|
||||
{ "fill",{ { "intervalStep", 10 },{ "threshold", .85f } } }
|
||||
{ "bytes",{ { "segmentThreshold", 300 },{ "threshold", .85f } } },
|
||||
{ "bytes_accum",{ { "segmentThreshold", 300 },{ "threshold", .85f } } },
|
||||
{ "count",{ { "segmentThreshold", 300 },{ "threshold", .85f } } },
|
||||
{ "fill",{ { "segmentThreshold", 300 },{ "threshold", .85f } } }
|
||||
};
|
||||
arangodb::iresearch::IResearchViewMeta meta;
|
||||
arangodb::velocypack::Builder builder;
|
||||
|
@ -466,10 +466,10 @@ SECTION("test_writeCustomizedValues") {
|
|||
|
||||
std::unordered_set<TRI_voc_cid_t> expectedCollections = { 42, 52, 62 };
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, double>> expectedCommitItemConsolidate = {
|
||||
{ "bytes",{ { "intervalStep", 101 },{ "threshold", .11f } } },
|
||||
{ "bytes_accum",{ { "intervalStep", 151 },{ "threshold", .151f } } },
|
||||
{ "count",{ { "intervalStep", 201 },{ "threshold", .21f } } },
|
||||
{ "fill",{ { "intervalStep", 301 },{ "threshold", .31f } } }
|
||||
{ "bytes",{ { "segmentThreshold", 101 },{ "threshold", .11f } } },
|
||||
{ "bytes_accum",{ { "segmentThreshold", 151 },{ "threshold", .151f } } },
|
||||
{ "count",{ { "segmentThreshold", 201 },{ "threshold", .21f } } },
|
||||
{ "fill",{ { "segmentThreshold", 301 },{ "threshold", .31f } } }
|
||||
};
|
||||
arangodb::velocypack::Builder builder;
|
||||
arangodb::velocypack::Slice tmpSlice;
|
||||
|
|
|
@ -94,7 +94,7 @@ class EdgeIndexIteratorMock final : public arangodb::IndexIterator {
|
|||
return "edge-index-iterator-mock";
|
||||
}
|
||||
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) {
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override {
|
||||
while (limit && _begin != _end && _keysIt.valid()) {
|
||||
auto key = _keysIt.value();
|
||||
|
||||
|
@ -175,7 +175,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
VPackBuilder& builder,
|
||||
bool withFigures,
|
||||
bool forPersistence
|
||||
) const {
|
||||
) const override {
|
||||
builder.openObject();
|
||||
Index::toVelocyPack(builder, withFigures, forPersistence);
|
||||
// hard-coded
|
||||
|
@ -184,7 +184,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
builder.close();
|
||||
}
|
||||
|
||||
void toVelocyPackFigures(VPackBuilder& builder) const {
|
||||
void toVelocyPackFigures(VPackBuilder& builder) const override {
|
||||
Index::toVelocyPackFigures(builder);
|
||||
|
||||
builder.add("from", VPackValue(VPackValueType::Object));
|
||||
|
@ -201,7 +201,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
arangodb::LocalDocumentId const& documentId,
|
||||
arangodb::velocypack::Slice const& doc,
|
||||
OperationMode
|
||||
) {
|
||||
) override {
|
||||
if (!doc.isObject()) {
|
||||
return { TRI_ERROR_INTERNAL };
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
arangodb::LocalDocumentId const&,
|
||||
arangodb::velocypack::Slice const& doc,
|
||||
OperationMode
|
||||
) {
|
||||
) override {
|
||||
if (!doc.isObject()) {
|
||||
return { TRI_ERROR_INTERNAL };
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
size_t itemsInIndex,
|
||||
size_t& estimatedItems,
|
||||
double& estimatedCost
|
||||
) const {
|
||||
) const override {
|
||||
arangodb::SimpleAttributeEqualityMatcher matcher(IndexAttributes);
|
||||
|
||||
return matcher.matchOne(
|
||||
|
@ -272,7 +272,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
arangodb::aql::AstNode const* node,
|
||||
arangodb::aql::Variable const*,
|
||||
bool
|
||||
) {
|
||||
) override {
|
||||
TRI_ASSERT(node->type == arangodb::aql::NODE_TYPE_OPERATOR_NARY_AND);
|
||||
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
@ -311,7 +311,7 @@ class EdgeIndexMock final : public arangodb::Index {
|
|||
arangodb::aql::AstNode* specializeCondition(
|
||||
arangodb::aql::AstNode* node,
|
||||
arangodb::aql::Variable const* reference
|
||||
) const {
|
||||
) const override {
|
||||
arangodb::SimpleAttributeEqualityMatcher matcher(IndexAttributes);
|
||||
|
||||
return matcher.specializeOne(this, node, reference);
|
||||
|
@ -1379,4 +1379,4 @@ bool TransactionStateMock::hasFailedOperations() const {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
Loading…
Reference in New Issue