1
0
Fork 0

Bug fix/internal issue #342: allow to bind a view name (#4554)

This commit is contained in:
Andrey Abramov 2018-02-13 23:53:01 +03:00 committed by Jan
parent dbfe4344f5
commit 1b7dd672c9
18 changed files with 2312 additions and 2054 deletions

View File

@ -586,6 +586,7 @@ AstNode* Ast::createNodeCollection(char const* name,
AstNode* node = createNode(NODE_TYPE_COLLECTION);
node->setStringValue(name, strlen(name));
node->dataSourceType = AstNode::DataSourceType::Collection;
_query->collections()->add(name, accessType);
@ -620,6 +621,7 @@ AstNode* Ast::createNodeView(char const* name) {
AstNode* node = createNode(NODE_TYPE_VIEW);
node->setStringValue(name, strlen(name));
node->dataSourceType = AstNode::DataSourceType::View;
auto* collections = _query->collections();
@ -678,7 +680,11 @@ AstNode* Ast::createNodeReference(Variable const* variable) {
}
/// @brief create an AST parameter node
AstNode* Ast::createNodeParameter(char const* name, size_t length) {
AstNode* Ast::createNodeParameter(
char const* name,
size_t length,
AstNode::DataSourceType dataSourceType /* = AstNode::DataSourceType::Invalid */
) {
if (name == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
@ -686,6 +692,7 @@ AstNode* Ast::createNodeParameter(char const* name, size_t length) {
AstNode* node = createNode(NODE_TYPE_PARAMETER);
node->setStringValue(name, length);
node->dataSourceType = dataSourceType;
// insert bind parameter name into list of found parameters
_bindParameters.emplace(name);
@ -1402,6 +1409,7 @@ void Ast::injectBindParameters(BindParameters& parameters) {
_query->registerError(TRI_ERROR_QUERY_BIND_PARAMETER_MISSING, param.c_str());
return nullptr;
}
auto const& it = p.find(param);
if (it == p.end()) {
@ -1416,74 +1424,107 @@ void Ast::injectBindParameters(BindParameters& parameters) {
auto& value = (*it).second.first;
TRI_ASSERT(!param.empty());
if (param[0] == '@') {
// collection parameter
TRI_ASSERT(value.isString());
// check if the collection was used in a data-modification query
bool isWriteCollection = false;
switch (node->getDataSourceType()) {
case AstNode::DataSourceType::Collection: {
// bound collection parameter
TRI_ASSERT(value.isString());
for (auto const& it : _writeCollections) {
if (it->type == NODE_TYPE_PARAMETER && StringRef(param) == StringRef(it->getStringValue(), it->getStringLength())) {
isWriteCollection = true;
break;
}
}
// check if the collection was used in a data-modification query
bool isWriteCollection = false;
// turn node into a collection node
char const* name = nullptr;
VPackValueLength length;
char const* stringValue = value.getString(length);
if (length > 0 && stringValue[0] >= '0' && stringValue[0] <= '9') {
// emergency translation of collection id to name
arangodb::CollectionNameResolver resolver(_query->vocbase());
std::string collectionName = resolver.getCollectionNameCluster(basics::StringUtils::uint64(stringValue, length));
if (collectionName.empty()) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
value.copyString().c_str());
}
name = _query->registerString(collectionName.c_str(), collectionName.size());
} else {
// TODO: can we get away without registering the string value here?
name = _query->registerString(stringValue, static_cast<size_t>(length));
}
TRI_ASSERT(name != nullptr);
node = createNodeCollection(name, isWriteCollection
? AccessMode::Type::WRITE
: AccessMode::Type::READ);
if (isWriteCollection) {
// must update AST info now for all nodes that contained this
// parameter
for (size_t i = 0; i < _writeCollections.size(); ++i) {
if (_writeCollections[i]->type == NODE_TYPE_PARAMETER &&
StringRef(param) == StringRef(_writeCollections[i]->getStringValue(), _writeCollections[i]->getStringLength())) {
_writeCollections[i] = node;
// no break here. replace all occurrences
for (auto const& it : _writeCollections) {
if (it->type == NODE_TYPE_PARAMETER && StringRef(param) == StringRef(it->getStringValue(), it->getStringLength())) {
isWriteCollection = true;
break;
}
}
}
} else {
node = nodeFromVPack(value, true);
if (node != nullptr) {
// already mark node as constant here
node->setFlag(DETERMINED_CONSTANT, VALUE_CONSTANT);
// mark node as simple
node->setFlag(DETERMINED_SIMPLE, VALUE_SIMPLE);
// mark node as executable on db-server
node->setFlag(DETERMINED_RUNONDBSERVER, VALUE_RUNONDBSERVER);
// mark node as non-throwing
node->setFlag(DETERMINED_THROWS);
// mark node as deterministic
node->setFlag(DETERMINED_NONDETERMINISTIC);
// turn node into a collection node
char const* name = nullptr;
VPackValueLength length;
char const* stringValue = value.getString(length);
// finally note that the node was created from a bind parameter
node->setFlag(FLAG_BIND_PARAMETER);
if (length > 0 && stringValue[0] >= '0' && stringValue[0] <= '9') {
// emergency translation of collection id to name
arangodb::CollectionNameResolver resolver(_query->vocbase());
std::string collectionName = resolver.getCollectionNameCluster(basics::StringUtils::uint64(stringValue, length));
if (collectionName.empty()) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
value.copyString().c_str());
}
name = _query->registerString(collectionName.c_str(), collectionName.size());
} else {
// TODO: can we get away without registering the string value here?
name = _query->registerString(stringValue, static_cast<size_t>(length));
}
TRI_ASSERT(name != nullptr);
node = createNodeCollection(name, isWriteCollection
? AccessMode::Type::WRITE
: AccessMode::Type::READ);
if (isWriteCollection) {
// must update AST info now for all nodes that contained this
// parameter
for (size_t i = 0; i < _writeCollections.size(); ++i) {
if (_writeCollections[i]->type == NODE_TYPE_PARAMETER &&
StringRef(param) == StringRef(_writeCollections[i]->getStringValue(), _writeCollections[i]->getStringLength())) {
_writeCollections[i] = node;
// no break here. replace all occurrences
}
}
}
} break;
case AstNode::DataSourceType::View: {
// bound view parameter
TRI_ASSERT(value.isString());
// turn node into a view node
char const* name = nullptr;
VPackValueLength length;
char const* stringValue = value.getString(length);
if (length > 0 && stringValue[0] >= '0' && stringValue[0] <= '9') {
// emergency translation of collection id to name
arangodb::CollectionNameResolver resolver(_query->vocbase());
std::string viewName = resolver.getViewNameCluster(basics::StringUtils::uint64(stringValue, length));
if (viewName .empty()) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_ARANGO_VIEW_NOT_FOUND,
value.copyString().c_str());
}
name = _query->registerString(viewName.c_str(), viewName.size());
} else {
// TODO: can we get away without registering the string value here?
name = _query->registerString(stringValue, static_cast<size_t>(length));
}
TRI_ASSERT(name != nullptr);
node = createNodeView(name);
} break;
default: {
// regular bound parameter
node = nodeFromVPack(value, true);
if (node != nullptr) {
// already mark node as constant here
node->setFlag(DETERMINED_CONSTANT, VALUE_CONSTANT);
// mark node as simple
node->setFlag(DETERMINED_SIMPLE, VALUE_SIMPLE);
// mark node as executable on db-server
node->setFlag(DETERMINED_RUNONDBSERVER, VALUE_RUNONDBSERVER);
// mark node as non-throwing
node->setFlag(DETERMINED_THROWS);
// mark node as deterministic
node->setFlag(DETERMINED_NONDETERMINISTIC);
// finally note that the node was created from a bind parameter
node->setFlag(FLAG_BIND_PARAMETER);
} break;
}
}
} else if (node->type == NODE_TYPE_BOUND_ATTRIBUTE_ACCESS) {
@ -3486,4 +3527,4 @@ AstNode* Ast::createNode(AstNodeType type) {
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

View File

@ -236,7 +236,11 @@ class Ast {
AstNode* createNodeReference(Variable const*);
/// @brief create an AST parameter node
AstNode* createNodeParameter(char const*, size_t);
AstNode* createNodeParameter(
char const* name,
size_t length,
AstNode::DataSourceType dataSourceType = AstNode::DataSourceType::Invalid
);
/// @brief create an AST quantifier node
AstNode* createNodeQuantifier(int64_t);

View File

@ -47,6 +47,13 @@
#include <velocypack/velocypack-aliases.h>
#include <array>
namespace {
arangodb::StringRef const VIEW_NODE_SUFFIX("\0v", 2);
arangodb::StringRef const COLLECTION_NODE_SUFFIX("\0c", 2);
}
using namespace arangodb::aql;
std::unordered_map<int, std::string const> const AstNode::Operators{
@ -760,7 +767,7 @@ AstNode::AstNode(std::function<void(AstNode*)> registerNode,
/// @brief destroy the node
AstNode::~AstNode() {
if (computedValue != nullptr) {
if (computedValue != nullptr && !isDataSource()) {
delete[] computedValue;
}
}

View File

@ -199,6 +199,12 @@ static_assert(NODE_TYPE_ARRAY < NODE_TYPE_OBJECT, "incorrect node types order");
struct AstNode {
friend class Ast;
enum class DataSourceType : uintptr_t {
Invalid = 0,
Collection,
View,
};
static std::unordered_map<int, std::string const> const Operators;
static std::unordered_map<int, std::string const> const TypeNames;
static std::unordered_map<int, std::string const> const ValueTypeNames;
@ -369,6 +375,25 @@ struct AstNode {
/// @brief whether or not a value node is of array type
inline bool isObject() const { return (type == NODE_TYPE_OBJECT); }
inline bool isDataSource() const noexcept {
switch (type) {
case NODE_TYPE_COLLECTION:
case NODE_TYPE_VIEW:
return true;
case NODE_TYPE_PARAMETER:
return value.type == VALUE_TYPE_STRING
&& value.length
&& value.value._string
&& '@' == value.value._string[0];
default:
return false;
}
}
inline DataSourceType getDataSourceType() const noexcept {
return dataSourceType;
}
/// @brief whether or not a value node is of type attribute access that
/// refers to a variable reference
AstNode const* getAttributeAccessForVariable(bool allowIndexedAccess) const {
@ -678,8 +703,13 @@ struct AstNode {
AstNodeValue value;
private:
/// @brief precomputed VPack value (used when executing expressions)
uint8_t mutable* computedValue;
union {
/// @brief precomputed VPack value (used when executing expressions)
uint8_t mutable* computedValue;
/// @brief type of the data source
DataSourceType dataSourceType;
};
/// @brief the node's sub nodes
std::vector<AstNode*> members;

File diff suppressed because it is too large Load Diff

View File

@ -76,47 +76,48 @@ extern int Aqldebug;
T_INTEGER = 285,
T_DOUBLE = 286,
T_PARAMETER = 287,
T_ASSIGN = 288,
T_NOT = 289,
T_AND = 290,
T_OR = 291,
T_NIN = 292,
T_REGEX_MATCH = 293,
T_REGEX_NON_MATCH = 294,
T_EQ = 295,
T_NE = 296,
T_LT = 297,
T_GT = 298,
T_LE = 299,
T_GE = 300,
T_LIKE = 301,
T_PLUS = 302,
T_MINUS = 303,
T_TIMES = 304,
T_DIV = 305,
T_MOD = 306,
T_QUESTION = 307,
T_COLON = 308,
T_SCOPE = 309,
T_RANGE = 310,
T_COMMA = 311,
T_OPEN = 312,
T_CLOSE = 313,
T_OBJECT_OPEN = 314,
T_OBJECT_CLOSE = 315,
T_ARRAY_OPEN = 316,
T_ARRAY_CLOSE = 317,
T_OUTBOUND = 318,
T_INBOUND = 319,
T_ANY = 320,
T_ALL = 321,
T_NONE = 322,
UMINUS = 323,
UPLUS = 324,
FUNCCALL = 325,
REFERENCE = 326,
INDEXED = 327,
EXPANSION = 328
T_DATA_SOURCE_PARAMETER = 288,
T_ASSIGN = 289,
T_NOT = 290,
T_AND = 291,
T_OR = 292,
T_NIN = 293,
T_REGEX_MATCH = 294,
T_REGEX_NON_MATCH = 295,
T_EQ = 296,
T_NE = 297,
T_LT = 298,
T_GT = 299,
T_LE = 300,
T_GE = 301,
T_LIKE = 302,
T_PLUS = 303,
T_MINUS = 304,
T_TIMES = 305,
T_DIV = 306,
T_MOD = 307,
T_QUESTION = 308,
T_COLON = 309,
T_SCOPE = 310,
T_RANGE = 311,
T_COMMA = 312,
T_OPEN = 313,
T_CLOSE = 314,
T_OBJECT_OPEN = 315,
T_OBJECT_CLOSE = 316,
T_ARRAY_OPEN = 317,
T_ARRAY_CLOSE = 318,
T_OUTBOUND = 319,
T_INBOUND = 320,
T_ANY = 321,
T_ALL = 322,
T_NONE = 323,
UMINUS = 324,
UPLUS = 325,
FUNCCALL = 326,
REFERENCE = 327,
INDEXED = 328,
EXPANSION = 329
};
#endif
@ -125,7 +126,7 @@ extern int Aqldebug;
union YYSTYPE
{
#line 20 "Aql/grammar.y" /* yacc.c:1909 */
#line 21 "Aql/grammar.y" /* yacc.c:1909 */
arangodb::aql::AstNode* node;
struct {
@ -135,7 +136,7 @@ union YYSTYPE
bool boolval;
int64_t intval;
#line 139 "Aql/grammar.hpp" /* yacc.c:1909 */
#line 140 "Aql/grammar.hpp" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -76,47 +76,48 @@ extern int Aqldebug;
T_INTEGER = 285,
T_DOUBLE = 286,
T_PARAMETER = 287,
T_ASSIGN = 288,
T_NOT = 289,
T_AND = 290,
T_OR = 291,
T_NIN = 292,
T_REGEX_MATCH = 293,
T_REGEX_NON_MATCH = 294,
T_EQ = 295,
T_NE = 296,
T_LT = 297,
T_GT = 298,
T_LE = 299,
T_GE = 300,
T_LIKE = 301,
T_PLUS = 302,
T_MINUS = 303,
T_TIMES = 304,
T_DIV = 305,
T_MOD = 306,
T_QUESTION = 307,
T_COLON = 308,
T_SCOPE = 309,
T_RANGE = 310,
T_COMMA = 311,
T_OPEN = 312,
T_CLOSE = 313,
T_OBJECT_OPEN = 314,
T_OBJECT_CLOSE = 315,
T_ARRAY_OPEN = 316,
T_ARRAY_CLOSE = 317,
T_OUTBOUND = 318,
T_INBOUND = 319,
T_ANY = 320,
T_ALL = 321,
T_NONE = 322,
UMINUS = 323,
UPLUS = 324,
FUNCCALL = 325,
REFERENCE = 326,
INDEXED = 327,
EXPANSION = 328
T_DATA_SOURCE_PARAMETER = 288,
T_ASSIGN = 289,
T_NOT = 290,
T_AND = 291,
T_OR = 292,
T_NIN = 293,
T_REGEX_MATCH = 294,
T_REGEX_NON_MATCH = 295,
T_EQ = 296,
T_NE = 297,
T_LT = 298,
T_GT = 299,
T_LE = 300,
T_GE = 301,
T_LIKE = 302,
T_PLUS = 303,
T_MINUS = 304,
T_TIMES = 305,
T_DIV = 306,
T_MOD = 307,
T_QUESTION = 308,
T_COLON = 309,
T_SCOPE = 310,
T_RANGE = 311,
T_COMMA = 312,
T_OPEN = 313,
T_CLOSE = 314,
T_OBJECT_OPEN = 315,
T_OBJECT_CLOSE = 316,
T_ARRAY_OPEN = 317,
T_ARRAY_CLOSE = 318,
T_OUTBOUND = 319,
T_INBOUND = 320,
T_ANY = 321,
T_ALL = 322,
T_NONE = 323,
UMINUS = 324,
UPLUS = 325,
FUNCCALL = 326,
REFERENCE = 327,
INDEXED = 328,
EXPANSION = 329
};
#endif
@ -125,7 +126,7 @@ extern int Aqldebug;
union YYSTYPE
{
#line 20 "Aql/grammar.y" /* yacc.c:1909 */
#line 21 "Aql/grammar.y" /* yacc.c:1909 */
arangodb::aql::AstNode* node;
struct {
@ -135,7 +136,7 @@ union YYSTYPE
bool boolval;
int64_t intval;
#line 139 "Aql/grammar.hpp" /* yacc.c:1909 */
#line 140 "Aql/grammar.hpp" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -15,6 +15,7 @@
#include "Basics/conversions.h"
#include "Basics/tri-strings.h"
#include "VocBase/AccessMode.h"
#include <iostream>
%}
%union {
@ -205,6 +206,7 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
%token T_INTEGER "integer number"
%token T_DOUBLE "number"
%token T_PARAMETER "bind parameter"
%token T_DATA_SOURCE_PARAMETER "bind data source parameter"
%token T_ASSIGN "assignment"
@ -282,6 +284,7 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
%type <node> T_INTEGER
%type <node> T_DOUBLE
%type <strval> T_PARAMETER;
%type <strval> T_DATA_SOURCE_PARAMETER;
%type <node> with_collection;
%type <node> sort_list;
%type <node> sort_element;
@ -328,6 +331,7 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
%type <node> view_name;
%type <node> in_or_into_collection;
%type <node> bind_parameter;
%type <node> bind_view;
%type <strval> variable_name;
%type <node> numeric_value;
%type <intval> update_or_replace;
@ -346,9 +350,11 @@ with_collection:
| bind_parameter {
char const* p = $1->getStringValue();
size_t const len = $1->getStringLength();
if (len < 1 || *p != '@') {
if (len < 2 || *p != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), p, yylloc.first_line, yylloc.first_column);
}
$$ = $1;
}
;
@ -1398,11 +1404,6 @@ graph_collection:
$$ = parser->ast()->createNodeValueString($1.value, $1.length);
}
| bind_parameter {
char const* p = $1->getStringValue();
size_t const len = $1->getStringLength();
if (len < 1 || *p != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), p, yylloc.first_line, yylloc.first_column);
}
$$ = $1;
}
| graph_direction T_STRING {
@ -1410,11 +1411,6 @@ graph_collection:
$$ = parser->ast()->createNodeCollectionDirection($1, tmp);
}
| graph_direction bind_parameter {
char const* p = $2->getStringValue();
size_t const len = $2->getStringLength();
if (len < 1 || *p != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), p, yylloc.first_line, yylloc.first_column);
}
$$ = parser->ast()->createNodeCollectionDirection($1, $2);
}
;
@ -1446,11 +1442,6 @@ graph_subject:
}
| T_GRAPH bind_parameter {
// graph name
char const* p = $2->getStringValue();
size_t const len = $2->getStringLength();
if (len < 1 || *p == '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), p, yylloc.first_line, yylloc.first_column);
}
$$ = $2;
}
| T_GRAPH T_QUOTED_STRING {
@ -1687,12 +1678,8 @@ collection_name:
| T_QUOTED_STRING {
$$ = parser->ast()->createNodeCollection($1.value, arangodb::AccessMode::Type::WRITE);
}
| T_PARAMETER {
if ($1.length < 2 || $1.value[0] != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), $1.value, yylloc.first_line, yylloc.first_column);
}
$$ = parser->ast()->createNodeParameter($1.value, $1.length);
| bind_parameter {
$$ = $1;
}
;
@ -1703,14 +1690,34 @@ view_name:
| T_QUOTED_STRING {
$$ = parser->ast()->createNodeView($1.value);
}
; // TODO: add parameter case
| bind_view {
$$ = $1;
}
;
bind_parameter:
T_PARAMETER {
T_DATA_SOURCE_PARAMETER {
if ($1.length < 2 || $1.value[0] != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), $1.value, yylloc.first_line, yylloc.first_column);
}
$$ = parser->ast()->createNodeParameter($1.value, $1.length, AstNode::DataSourceType::Collection);
}
| T_PARAMETER {
$$ = parser->ast()->createNodeParameter($1.value, $1.length);
}
;
bind_view:
T_DATA_SOURCE_PARAMETER {
if ($1.length < 2 || $1.value[0] != '@') {
parser->registerParseError(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE, TRI_errno_string(TRI_ERROR_QUERY_BIND_PARAMETER_TYPE), $1.value, yylloc.first_line, yylloc.first_column);
}
$$ = parser->ast()->createNodeParameter($1.value, $1.length, AstNode::DataSourceType::View);
}
;
object_element_name:
T_STRING {
$$ = $1;

View File

@ -555,8 +555,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
#define YY_NUM_RULES 101
#define YY_END_OF_BUFFER 102
#define YY_NUM_RULES 102
#define YY_END_OF_BUFFER 103
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@ -564,37 +564,37 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_accept[263] =
static yyconst flex_int16_t yy_accept[269] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 102, 100, 87, 88,
44, 74, 100, 51, 100, 79, 57, 58, 49, 47,
56, 48, 100, 50, 84, 84, 54, 42, 43, 40,
52, 100, 63, 63, 63, 63, 63, 63, 63, 63,
0, 0, 0, 0, 0, 0, 103, 101, 88, 89,
44, 74, 101, 51, 101, 79, 57, 58, 49, 47,
56, 48, 101, 50, 84, 84, 54, 42, 43, 40,
52, 101, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 61, 62,
100, 64, 59, 100, 60, 100, 68, 67, 68, 65,
101, 64, 59, 101, 60, 101, 68, 67, 68, 65,
73, 72, 73, 73, 83, 82, 80, 83, 78, 77,
75, 78, 91, 90, 94, 96, 95, 99, 98, 98,
99, 87, 38, 36, 63, 45, 55, 92, 89, 0,
75, 78, 92, 91, 95, 97, 96, 100, 99, 99,
100, 88, 38, 36, 63, 45, 55, 93, 90, 0,
0, 84, 53, 41, 37, 35, 39, 86, 0, 0,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 15, 63, 63, 63, 63, 14, 63, 63,
63, 63, 63, 63, 63, 63, 63, 0, 46, 69,
66, 71, 70, 81, 76, 91, 94, 93, 97, 85,
0, 85, 86, 86, 63, 28, 13, 27, 10, 63,
63, 63, 63, 63, 1, 63, 63, 63, 63, 2,
63, 63, 63, 12, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 86, 86,
63, 63, 11, 63, 63, 63, 63, 63, 63, 16,
66, 71, 70, 81, 76, 92, 95, 94, 98, 85,
0, 85, 86, 87, 0, 86, 63, 28, 13, 27,
10, 63, 63, 63, 63, 63, 1, 63, 63, 63,
63, 2, 63, 63, 63, 12, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
87, 87, 86, 86, 63, 63, 11, 63, 63, 63,
30, 63, 29, 32, 63, 63, 63, 63, 63, 6,
33, 63, 63, 31, 17, 63, 63, 63, 34, 63,
23, 63, 63, 7, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 3, 63, 19, 63, 18, 63,
4, 63, 20, 22, 63, 5, 63, 26, 63, 21,
63, 63, 8, 25, 63, 9, 63, 63, 63, 63,
24, 0
63, 63, 63, 16, 30, 63, 29, 32, 63, 63,
63, 63, 63, 6, 33, 63, 63, 31, 17, 87,
87, 63, 63, 63, 34, 63, 23, 63, 63, 7,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
3, 63, 19, 63, 18, 63, 4, 63, 20, 22,
63, 5, 63, 26, 63, 21, 63, 63, 8, 25,
63, 9, 63, 63, 63, 63, 24, 0
} ;
static yyconst YY_CHAR yy_ec[256] =
@ -642,77 +642,81 @@ static yyconst YY_CHAR yy_meta[82] =
1
} ;
static yyconst flex_uint16_t yy_base[286] =
static yyconst flex_uint16_t yy_base[297] =
{ 0,
0, 0, 79, 80, 81, 84, 85, 86, 87, 88,
420, 417, 93, 94, 83, 105, 419, 572, 412, 572,
76, 572, 0, 572, 400, 572, 572, 572, 572, 572,
572, 572, 378, 87, 84, 93, 369, 336, 79, 276,
572, 88, 83, 0, 79, 94, 134, 79, 88, 127,
119, 121, 86, 136, 108, 130, 138, 144, 572, 572,
228, 572, 572, 173, 572, 168, 572, 572, 0, 572,
572, 572, 0, 161, 572, 572, 572, 0, 572, 572,
572, 0, 0, 572, 0, 572, 216, 572, 572, 572,
136, 177, 572, 572, 0, 572, 572, 572, 572, 84,
434, 430, 93, 94, 83, 105, 430, 587, 426, 587,
76, 587, 0, 587, 419, 587, 587, 587, 587, 587,
587, 587, 410, 87, 84, 93, 399, 396, 79, 393,
587, 88, 83, 0, 79, 94, 134, 79, 88, 127,
119, 121, 86, 136, 108, 130, 138, 144, 587, 587,
362, 587, 587, 327, 587, 309, 587, 587, 0, 587,
587, 587, 0, 220, 587, 587, 587, 0, 587, 587,
587, 0, 0, 587, 0, 587, 280, 587, 587, 587,
136, 245, 587, 587, 0, 587, 587, 587, 587, 84,
192, 164, 572, 572, 572, 572, 572, 0, 156, 121,
0, 152, 150, 170, 164, 167, 166, 170, 178, 179,
175, 169, 194, 175, 188, 186, 191, 0, 185, 222,
192, 192, 190, 225, 209, 203, 251, 118, 572, 572,
572, 572, 572, 572, 572, 0, 0, 572, 572, 253,
257, 259, 0, 89, 216, 0, 0, 0, 0, 236,
251, 237, 243, 244, 0, 248, 251, 254, 252, 0,
264, 262, 267, 0, 262, 274, 264, 268, 261, 267,
266, 272, 288, 287, 273, 288, 0, 309, 73, 0,
293, 304, 0, 301, 308, 309, 307, 298, 302, 0,
192, 164, 587, 587, 587, 587, 587, 0, 189, 186,
0, 149, 150, 170, 156, 155, 161, 165, 176, 178,
174, 169, 193, 173, 188, 186, 191, 0, 185, 221,
193, 192, 194, 225, 191, 202, 251, 180, 587, 587,
587, 587, 587, 587, 587, 0, 0, 587, 587, 253,
256, 258, 0, 0, 127, 121, 216, 0, 0, 0,
0, 230, 222, 235, 237, 237, 0, 246, 248, 254,
250, 0, 261, 259, 266, 0, 261, 272, 261, 265,
259, 263, 265, 280, 287, 286, 271, 287, 0, 304,
0, 118, 89, 0, 296, 300, 0, 299, 304, 305,
304, 294, 298, 0, 0, 298, 0, 0, 303, 300,
321, 307, 306, 0, 0, 307, 310, 0, 0, 73,
0, 321, 327, 318, 0, 317, 0, 321, 320, 0,
323, 341, 344, 335, 350, 352, 341, 362, 346, 364,
0, 364, 0, 357, 0, 364, 0, 354, 0, 0,
354, 0, 358, 0, 374, 0, 361, 376, 0, 0,
66, 0, 368, 381, 367, 380, 0, 587, 441, 448,
455, 462, 469, 476, 483, 104, 487, 491, 493, 500,
507, 514, 521, 528, 535, 539, 543, 547, 551, 555,
559, 563, 567, 571, 575, 579
0, 302, 0, 0, 308, 304, 315, 310, 309, 0,
0, 310, 313, 0, 0, 324, 329, 320, 0, 318,
0, 325, 321, 0, 327, 344, 348, 339, 353, 358,
346, 367, 351, 368, 0, 368, 0, 361, 0, 368,
0, 358, 0, 0, 359, 0, 362, 0, 378, 0,
365, 380, 0, 0, 66, 0, 371, 387, 371, 385,
0, 572, 446, 453, 460, 467, 474, 481, 488, 104,
492, 496, 498, 505, 512, 519, 526, 533, 540, 544,
548, 552, 556, 560, 564
} ;
static yyconst flex_int16_t yy_def[286] =
static yyconst flex_int16_t yy_def[297] =
{ 0,
262, 1, 263, 263, 264, 264, 265, 265, 266, 266,
267, 267, 268, 268, 269, 269, 262, 262, 262, 262,
262, 262, 270, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 271, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 262, 262,
273, 262, 262, 262, 262, 262, 262, 262, 274, 262,
262, 262, 275, 262, 262, 262, 262, 276, 262, 262,
262, 277, 278, 262, 279, 262, 262, 262, 262, 262,
262, 262, 262, 262, 272, 262, 262, 262, 262, 262,
268, 1, 269, 269, 270, 270, 271, 271, 272, 272,
273, 273, 274, 274, 275, 275, 268, 268, 268, 268,
268, 268, 276, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 277, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 268, 268,
279, 268, 268, 268, 268, 268, 268, 268, 280, 268,
268, 268, 281, 268, 268, 268, 268, 282, 268, 268,
268, 283, 284, 268, 285, 268, 268, 268, 268, 268,
268, 268, 268, 268, 278, 268, 268, 268, 268, 268,
262, 262, 262, 262, 262, 262, 262, 280, 271, 281,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 282, 273, 262, 262,
262, 262, 262, 262, 262, 278, 279, 262, 262, 262,
262, 262, 280, 283, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 284, 282, 283, 285,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
268, 268, 268, 268, 268, 268, 268, 286, 287, 288,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 289, 279, 268, 268,
268, 268, 268, 268, 268, 284, 285, 268, 268, 268,
268, 268, 286, 290, 291, 292, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 293, 289,
290, 294, 292, 295, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 294,
296, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 0, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
272, 0, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262
} ;
static yyconst flex_uint16_t yy_nxt[654] =
static yyconst flex_uint16_t yy_nxt[669] =
{ 0,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
@ -726,69 +730,70 @@ static yyconst flex_uint16_t yy_nxt[654] =
80, 81, 81, 77, 77, 86, 86, 93, 98, 100,
105, 150, 150, 99, 87, 87, 89, 90, 100, 95,
102, 102, 109, 101, 112, 130, 91, 257, 116, 113,
122, 114, 101, 117, 190, 115, 123, 118, 69, 69,
102, 102, 109, 101, 112, 130, 91, 263, 116, 113,
122, 114, 101, 117, 221, 115, 123, 118, 69, 69,
73, 70, 70, 73, 78, 78, 82, 82, 91, 110,
190, 101, 112, 130, 91, 116, 113, 122, 114, 133,
194, 101, 112, 130, 91, 116, 113, 122, 114, 133,
101, 117, 115, 123, 94, 118, 124, 106, 126, 119,
125, 74, 128, 127, 74, 129, 91, 120, 131, 138,
134, 135, 110, 121, 149, 132, 133, 136, 92, 100,
262, 102, 102, 155, 124, 126, 156, 119, 125, 128,
127, 159, 129, 101, 166, 120, 131, 134, 157, 135,
125, 74, 128, 127, 74, 129, 91, 120, 131, 221,
134, 135, 194, 121, 149, 132, 133, 136, 155, 100,
157, 102, 102, 161, 124, 126, 158, 119, 125, 128,
127, 162, 129, 101, 168, 120, 131, 134, 159, 135,
121, 149, 132, 160, 151, 136, 151, 110, 161, 152,
152, 155, 162, 156, 163, 164, 165, 158, 170, 159,
167, 101, 166, 171, 173, 172, 157, 175, 176, 174,
160, 180, 148, 181, 182, 161, 168, 169, 185, 162,
143, 163, 164, 165, 158, 170, 186, 140, 167, 139,
171, 173, 172, 183, 175, 176, 174, 191, 180, 177,
181, 182, 178, 168, 169, 179, 185, 184, 187, 187,
150, 150, 192, 186, 152, 152, 152, 152, 193, 138,
194, 183, 101, 199, 191, 195, 177, 196, 197, 178,
198, 200, 179, 201, 184, 202, 203, 107, 204, 192,
121, 149, 132, 163, 151, 136, 151, 164, 157, 152,
152, 161, 165, 158, 166, 167, 172, 160, 162, 169,
187, 101, 168, 173, 175, 174, 159, 177, 178, 176,
163, 138, 182, 183, 164, 170, 171, 110, 184, 165,
155, 166, 167, 172, 160, 188, 92, 169, 187, 197,
173, 175, 174, 185, 177, 178, 176, 195, 179, 182,
183, 180, 170, 171, 181, 184, 196, 186, 189, 189,
150, 150, 188, 152, 152, 152, 152, 197, 198, 199,
200, 185, 101, 203, 195, 179, 201, 202, 180, 204,
205, 181, 206, 196, 186, 207, 148, 208, 209, 143,
205, 211, 187, 206, 207, 208, 193, 194, 209, 210,
101, 199, 195, 212, 196, 197, 213, 198, 200, 214,
215, 201, 216, 202, 203, 204, 187, 187, 205, 211,
206, 207, 208, 217, 218, 209, 210, 219, 220, 221,
227, 212, 222, 223, 213, 224, 214, 225, 215, 226,
216, 228, 229, 230, 231, 232, 233, 104, 234, 235,
187, 217, 218, 236, 237, 219, 220, 221, 227, 222,
223, 238, 224, 239, 225, 240, 226, 241, 228, 229,
230, 231, 242, 232, 233, 234, 235, 243, 103, 244,
236, 237, 245, 97, 246, 247, 248, 250, 238, 249,
210, 211, 189, 212, 213, 198, 199, 200, 214, 215,
101, 203, 216, 201, 202, 217, 204, 218, 205, 219,
206, 189, 189, 207, 208, 222, 209, 210, 211, 223,
212, 213, 224, 225, 226, 214, 227, 215, 228, 229,
216, 230, 231, 217, 218, 232, 233, 219, 234, 235,
236, 237, 238, 222, 239, 189, 240, 223, 241, 242,
224, 225, 226, 243, 227, 228, 229, 244, 230, 231,
245, 246, 232, 247, 233, 234, 235, 236, 237, 248,
238, 249, 239, 240, 250, 241, 242, 251, 140, 252,
243, 253, 254, 256, 244, 255, 257, 258, 245, 246,
251, 239, 252, 240, 241, 253, 254, 96, 255, 256,
242, 258, 259, 92, 260, 243, 244, 261, 262, 84,
245, 246, 84, 247, 248, 250, 249, 251, 262, 252,
262, 262, 253, 262, 254, 255, 262, 256, 258, 262,
259, 260, 262, 262, 262, 261, 67, 67, 67, 67,
67, 67, 67, 71, 71, 71, 71, 71, 71, 71,
75, 75, 75, 75, 75, 75, 75, 79, 79, 79,
79, 79, 79, 79, 83, 83, 83, 83, 83, 83,
83, 85, 85, 85, 85, 85, 85, 85, 88, 88,
88, 88, 88, 88, 88, 108, 108, 108, 108, 111,
247, 259, 260, 139, 261, 262, 265, 248, 264, 249,
266, 250, 267, 138, 107, 251, 252, 104, 103, 253,
254, 256, 255, 257, 258, 97, 96, 92, 259, 268,
260, 261, 84, 262, 265, 264, 84, 266, 268, 268,
267, 67, 67, 67, 67, 67, 67, 67, 71, 71,
71, 71, 71, 71, 71, 75, 75, 75, 75, 75,
75, 75, 79, 79, 79, 79, 79, 79, 79, 83,
83, 83, 83, 83, 83, 83, 85, 85, 85, 85,
85, 85, 85, 88, 88, 88, 88, 88, 88, 88,
108, 108, 108, 108, 111, 268, 111, 111, 137, 137,
262, 111, 111, 137, 137, 141, 262, 141, 141, 141,
141, 141, 142, 262, 142, 142, 142, 142, 142, 144,
262, 144, 144, 144, 144, 144, 145, 262, 145, 145,
145, 145, 145, 146, 262, 146, 146, 146, 146, 146,
147, 262, 262, 147, 147, 147, 147, 153, 262, 153,
153, 154, 262, 154, 154, 188, 262, 188, 188, 189,
262, 189, 189, 187, 262, 187, 187, 190, 262, 190,
190, 17, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
141, 268, 141, 141, 141, 141, 141, 142, 268, 142,
142, 142, 142, 142, 144, 268, 144, 144, 144, 144,
144, 145, 268, 145, 145, 145, 145, 145, 146, 268,
146, 146, 146, 146, 146, 147, 268, 268, 147, 147,
147, 147, 153, 268, 153, 153, 154, 268, 154, 154,
156, 268, 156, 156, 190, 268, 190, 190, 191, 268,
191, 191, 192, 268, 192, 192, 193, 268, 193, 193,
189, 268, 189, 189, 220, 268, 220, 220, 194, 268,
194, 194, 221, 268, 221, 221, 17, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268
} ;
static yyconst flex_int16_t yy_chk[654] =
static yyconst flex_int16_t yy_chk[669] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -801,79 +806,80 @@ static yyconst flex_int16_t yy_chk[654] =
1, 3, 4, 5, 15, 15, 6, 7, 8, 9,
10, 9, 10, 7, 8, 13, 14, 21, 34, 35,
39, 100, 100, 34, 13, 14, 16, 16, 36, 270,
36, 36, 42, 35, 43, 53, 15, 255, 45, 43,
48, 43, 36, 46, 189, 43, 49, 46, 3, 4,
39, 100, 100, 34, 13, 14, 16, 16, 36, 276,
36, 36, 42, 35, 43, 53, 15, 261, 45, 43,
48, 43, 36, 46, 220, 43, 49, 46, 3, 4,
5, 3, 4, 6, 7, 8, 9, 10, 16, 42,
154, 35, 43, 53, 15, 45, 43, 48, 43, 55,
193, 35, 43, 53, 15, 45, 43, 48, 43, 55,
36, 46, 43, 49, 21, 46, 50, 39, 51, 47,
50, 5, 52, 51, 6, 52, 16, 47, 54, 138,
56, 57, 110, 47, 91, 54, 55, 58, 92, 102,
109, 102, 102, 112, 50, 51, 113, 47, 50, 52,
51, 115, 52, 102, 122, 47, 54, 56, 114, 57,
50, 5, 52, 51, 6, 52, 16, 47, 54, 192,
56, 57, 156, 47, 91, 54, 55, 58, 155, 102,
112, 102, 102, 115, 50, 51, 113, 47, 50, 52,
51, 116, 52, 102, 122, 47, 54, 56, 114, 57,
47, 91, 54, 116, 101, 58, 101, 109, 117, 101,
101, 112, 118, 113, 119, 120, 121, 114, 124, 115,
123, 102, 122, 125, 126, 125, 114, 127, 129, 126,
116, 131, 87, 132, 133, 117, 123, 123, 135, 118,
74, 119, 120, 121, 114, 124, 136, 66, 123, 64,
125, 126, 125, 134, 127, 129, 126, 155, 131, 130,
132, 133, 130, 123, 123, 130, 135, 134, 137, 137,
150, 150, 160, 136, 151, 151, 152, 152, 161, 61,
162, 134, 150, 168, 155, 163, 130, 164, 166, 130,
167, 169, 130, 171, 134, 172, 173, 40, 175, 160,
47, 91, 54, 117, 101, 58, 101, 118, 112, 101,
101, 115, 119, 113, 120, 121, 124, 114, 116, 123,
135, 102, 122, 125, 126, 125, 114, 127, 129, 126,
117, 138, 131, 132, 118, 123, 123, 110, 133, 119,
109, 120, 121, 124, 114, 136, 92, 123, 135, 163,
125, 126, 125, 134, 127, 129, 126, 157, 130, 131,
132, 130, 123, 123, 130, 133, 162, 134, 137, 137,
150, 150, 136, 151, 151, 152, 152, 163, 164, 165,
166, 134, 150, 170, 157, 130, 168, 169, 130, 171,
173, 130, 174, 162, 134, 175, 87, 177, 178, 74,
176, 182, 137, 177, 178, 179, 161, 162, 180, 181,
150, 168, 163, 183, 164, 166, 184, 167, 169, 185,
186, 171, 191, 172, 173, 175, 188, 188, 176, 182,
177, 178, 179, 192, 194, 180, 181, 195, 196, 197,
207, 183, 198, 199, 184, 202, 185, 205, 186, 206,
191, 208, 209, 212, 213, 216, 217, 38, 218, 220,
188, 192, 194, 222, 223, 195, 196, 197, 207, 198,
199, 225, 202, 226, 205, 227, 206, 228, 208, 209,
212, 213, 229, 216, 217, 218, 220, 230, 37, 231,
222, 223, 232, 33, 233, 234, 236, 240, 225, 238,
179, 180, 137, 181, 182, 164, 165, 166, 183, 184,
150, 170, 185, 168, 169, 186, 171, 187, 173, 188,
174, 190, 190, 175, 177, 195, 178, 179, 180, 196,
181, 182, 198, 199, 200, 183, 201, 184, 202, 203,
185, 206, 209, 186, 187, 210, 211, 188, 212, 213,
216, 217, 222, 195, 223, 190, 224, 196, 226, 228,
198, 199, 200, 229, 201, 202, 203, 231, 206, 209,
232, 233, 210, 234, 211, 212, 213, 216, 217, 235,
222, 236, 223, 224, 237, 226, 228, 238, 66, 239,
229, 240, 242, 246, 231, 244, 248, 251, 232, 233,
242, 226, 245, 227, 228, 247, 249, 25, 251, 252,
229, 257, 258, 19, 259, 230, 231, 260, 17, 12,
232, 233, 11, 234, 236, 240, 238, 242, 0, 245,
0, 0, 247, 0, 249, 251, 0, 252, 257, 0,
258, 259, 0, 0, 0, 260, 263, 263, 263, 263,
263, 263, 263, 264, 264, 264, 264, 264, 264, 264,
265, 265, 265, 265, 265, 265, 265, 266, 266, 266,
266, 266, 266, 266, 267, 267, 267, 267, 267, 267,
267, 268, 268, 268, 268, 268, 268, 268, 269, 269,
269, 269, 269, 269, 269, 271, 271, 271, 271, 272,
234, 253, 255, 64, 257, 258, 264, 235, 263, 236,
265, 237, 266, 61, 40, 238, 239, 38, 37, 240,
242, 246, 244, 248, 251, 33, 25, 19, 253, 17,
255, 257, 12, 258, 264, 263, 11, 265, 0, 0,
266, 269, 269, 269, 269, 269, 269, 269, 270, 270,
270, 270, 270, 270, 270, 271, 271, 271, 271, 271,
271, 271, 272, 272, 272, 272, 272, 272, 272, 273,
273, 273, 273, 273, 273, 273, 274, 274, 274, 274,
274, 274, 274, 275, 275, 275, 275, 275, 275, 275,
277, 277, 277, 277, 278, 0, 278, 278, 279, 279,
0, 272, 272, 273, 273, 274, 0, 274, 274, 274,
274, 274, 275, 0, 275, 275, 275, 275, 275, 276,
0, 276, 276, 276, 276, 276, 277, 0, 277, 277,
277, 277, 277, 278, 0, 278, 278, 278, 278, 278,
279, 0, 0, 279, 279, 279, 279, 280, 0, 280,
280, 281, 0, 281, 281, 282, 0, 282, 282, 283,
0, 283, 283, 284, 0, 284, 284, 285, 0, 285,
285, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
280, 0, 280, 280, 280, 280, 280, 281, 0, 281,
281, 281, 281, 281, 282, 0, 282, 282, 282, 282,
282, 283, 0, 283, 283, 283, 283, 283, 284, 0,
284, 284, 284, 284, 284, 285, 0, 0, 285, 285,
285, 285, 286, 0, 286, 286, 287, 0, 287, 287,
288, 0, 288, 288, 289, 0, 289, 289, 290, 0,
290, 290, 291, 0, 291, 291, 292, 0, 292, 292,
293, 0, 293, 293, 294, 0, 294, 294, 295, 0,
295, 295, 296, 0, 296, 296, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
262, 262, 262
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
268, 268, 268, 268, 268, 268, 268, 268
} ;
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[102] =
static yyconst flex_int32_t yy_rule_can_match_eol[103] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, };
0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@ -1381,13 +1387,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 263 )
if ( yy_current_state >= 269 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp;
}
while ( yy_current_state != 262 );
while ( yy_current_state != 268 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@ -2030,23 +2036,36 @@ case 86:
YY_RULE_SETUP
{
/* bind parameters must start with a @
if followed by another @, this is a collection name parameter */
if followed by another @, this is a collection name or a view name parameter */
yylval->strval.value = yyextra->query()->registerString(yytext + 1, yyleng - 1);
yylval->strval.length = yyleng - 1;
return T_PARAMETER;
}
YY_BREAK
/* ---------------------------------------------------------------------------
* whitespace etc.
* bind data source parameters
* --------------------------------------------------------------------------- */
case 87:
YY_RULE_SETUP
{
/* bind parameters must start with a @
if followed by another @, this is a collection name or a view name parameter */
yylval->strval.value = yyextra->query()->registerString(yytext + 1, yyleng - 1);
yylval->strval.length = yyleng - 1;
return T_DATA_SOURCE_PARAMETER;
}
YY_BREAK
/* ---------------------------------------------------------------------------
* whitespace etc.
* --------------------------------------------------------------------------- */
case 88:
YY_RULE_SETUP
{
/* whitespace is ignored */
}
YY_BREAK
case 88:
/* rule 88 can match eol */
case 89:
/* rule 89 can match eol */
YY_RULE_SETUP
{
yycolumn = 0;
@ -2055,14 +2074,14 @@ YY_RULE_SETUP
/* ---------------------------------------------------------------------------
* comments
* --------------------------------------------------------------------------- */
case 89:
case 90:
YY_RULE_SETUP
{
BEGIN(COMMENT_SINGLE);
}
YY_BREAK
case 90:
/* rule 90 can match eol */
case 91:
/* rule 91 can match eol */
YY_RULE_SETUP
{
/* line numbers are counted elsewhere already */
@ -2070,38 +2089,38 @@ YY_RULE_SETUP
BEGIN(INITIAL);
}
YY_BREAK
case 91:
case 92:
YY_RULE_SETUP
{
/* everything else */
}
YY_BREAK
case 92:
case 93:
YY_RULE_SETUP
{
BEGIN(COMMENT_MULTI);
}
YY_BREAK
case 93:
case 94:
YY_RULE_SETUP
{
BEGIN(INITIAL);
}
YY_BREAK
case 94:
case 95:
YY_RULE_SETUP
{
// eat comment in chunks
}
YY_BREAK
case 95:
case 96:
YY_RULE_SETUP
{
// eat the lone star
}
YY_BREAK
case 96:
/* rule 96 can match eol */
case 97:
/* rule 97 can match eol */
YY_RULE_SETUP
{
/* line numbers are counted elsewhere already */
@ -2111,7 +2130,7 @@ YY_RULE_SETUP
/* ---------------------------------------------------------------------------
* special transformation for NOT IN to T_NIN
* --------------------------------------------------------------------------- */
case 97:
case 98:
YY_RULE_SETUP
{
/* T_NOT + T_IN => T_NIN */
@ -2119,14 +2138,14 @@ YY_RULE_SETUP
return T_NIN;
}
YY_BREAK
case 98:
/* rule 98 can match eol */
case 99:
/* rule 99 can match eol */
YY_RULE_SETUP
{
/* ignore whitespace */
}
YY_BREAK
case 99:
case 100:
YY_RULE_SETUP
{
/* found something different to T_IN */
@ -2145,14 +2164,14 @@ case YY_STATE_EOF(NOT):
return T_NOT;
}
YY_BREAK
case 100:
case 101:
YY_RULE_SETUP
{
/* anything else is returned as it is */
return (int) yytext[0];
}
YY_BREAK
case 101:
case 102:
YY_RULE_SETUP
ECHO;
YY_BREAK
@ -2464,7 +2483,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 263 )
if ( yy_current_state >= 269 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
@ -2494,11 +2513,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 263 )
if ( yy_current_state >= 269 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_is_jam = (yy_current_state == 262);
yy_is_jam = (yy_current_state == 268);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;

View File

@ -507,14 +507,26 @@ class Parser;
* bind parameters
* --------------------------------------------------------------------------- */
@@?(_+[a-zA-Z0-9]+[a-zA-Z0-9_]*|[a-zA-Z0-9][a-zA-Z0-9_]*) {
@(_+[a-zA-Z0-9]+[a-zA-Z0-9_]*|[a-zA-Z0-9][a-zA-Z0-9_]*) {
/* bind parameters must start with a @
if followed by another @, this is a collection name parameter */
if followed by another @, this is a collection name or a view name parameter */
yylval->strval.value = yyextra->query()->registerString(yytext + 1, yyleng - 1);
yylval->strval.length = yyleng - 1;
return T_PARAMETER;
}
/* ---------------------------------------------------------------------------
* bind data source parameters
* --------------------------------------------------------------------------- */
@@(_+[a-zA-Z0-9]+[a-zA-Z0-9_]*|[a-zA-Z0-9][a-zA-Z0-9_]*) {
/* bind parameters must start with a @
if followed by another @, this is a collection name or a view name parameter */
yylval->strval.value = yyextra->query()->registerString(yytext + 1, yyleng - 1);
yylval->strval.length = yyleng - 1;
return T_DATA_SOURCE_PARAMETER;
}
/* ---------------------------------------------------------------------------
* whitespace etc.
* --------------------------------------------------------------------------- */

View File

@ -385,8 +385,6 @@ class WBReader final : public rocksdb::WriteBatch::Handler {
/// parse the WAL with the above handler parser class
Result RocksDBRecoveryManager::parseRocksWAL() {
std::unique_ptr<WBReader> handler;
Result shutdownRv;
Result res = basics::catchToResult([&]() -> Result {
@ -398,7 +396,7 @@ Result RocksDBRecoveryManager::parseRocksWAL() {
}
// Tell the WriteBatch reader the transaction markers to look for
handler = std::make_unique<WBReader>(engine->settingsManager()->counterSeqs());
WBReader handler(engine->settingsManager()->counterSeqs());
auto minTick = std::min(engine->settingsManager()->earliestSeqNeeded(),
engine->releasedTick());
@ -413,8 +411,8 @@ Result RocksDBRecoveryManager::parseRocksWAL() {
s = iterator->status();
if (s.ok()) {
rocksdb::BatchResult batch = iterator->GetBatch();
handler->currentSeqNum = batch.sequence;
s = batch.writeBatchPtr->Iterate(handler.get());
handler.currentSeqNum = batch.sequence;
s = batch.writeBatchPtr->Iterate(&handler);
}
@ -431,8 +429,8 @@ Result RocksDBRecoveryManager::parseRocksWAL() {
if (rv.ok()) {
LOG_TOPIC(TRACE, Logger::ENGINES)
<< "finished WAL scan with " << handler->deltas.size();
for (auto& pair : handler->deltas) {
<< "finished WAL scan with " << handler.deltas.size();
for (auto& pair : handler.deltas) {
engine->settingsManager()->updateCounter(pair.first, pair.second);
LOG_TOPIC(TRACE, Logger::ENGINES)
<< "WAL recovered " << pair.second.added() << " PUTs and "
@ -440,16 +438,16 @@ Result RocksDBRecoveryManager::parseRocksWAL() {
}
}
}
shutdownRv = handler.shutdownWBReader();
return rv;
});
shutdownRv = handler->shutdownWBReader();
if(res.ok()) {
if (res.ok()) {
res = std::move(shutdownRv);
} else {
if(shutdownRv.fail()){
if (shutdownRv.fail()){
res.reset(res.errorNumber(), res.errorMessage() + " - " + shutdownRv.errorMessage());
}
}

View File

@ -314,6 +314,18 @@ std::string CollectionNameResolver::localNameLookup(TRI_voc_cid_t cid) const {
return name;
}
std::string CollectionNameResolver::getViewNameCluster(
TRI_voc_cid_t cid
) const {
if (!ServerState::isClusterRole(_serverRole)) {
// This handles the case of a standalone server
return _vocbase->viewName(cid);
}
// FIXME not supported
return StaticStrings::Empty;
}
bool CollectionNameResolver::visitCollections(
std::function<bool(TRI_voc_cid_t)> const& visitor, TRI_voc_cid_t cid
) const {
@ -344,4 +356,4 @@ bool CollectionNameResolver::visitCollections(
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

View File

@ -120,10 +120,17 @@ class CollectionNameResolver {
std::string getCollectionName(std::string const& nameOrId) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief look up a cluster-wide view name for a cluster-wide view id
//////////////////////////////////////////////////////////////////////////////
std::string getViewNameCluster(TRI_voc_cid_t cid) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief invoke visitor on all collections that map to the specified 'cid'
/// @return visitation was successful
//////////////////////////////////////////////////////////////////////////////
bool visitCollections(
std::function<bool(TRI_voc_cid_t)> const& visitor, TRI_voc_cid_t cid
) const;
@ -161,4 +168,4 @@ class CollectionNameResolver {
};
}
#endif
#endif

View File

@ -961,6 +961,21 @@ std::string TRI_vocbase_t::collectionName(TRI_voc_cid_t id) {
return (*it).second->name();
}
/// @brief gets a view name by a view id
/// the name is fetched under a lock to make this thread-safe.
/// returns empty string if the view does not exist.
std::string TRI_vocbase_t::viewName(TRI_voc_cid_t id) const {
RECURSIVE_READ_LOCKER(_viewsLock, _viewsLockWriteOwner);
auto it = _viewsById.find(id);
if (it == _viewsById.end()) {
return StaticStrings::Empty;
}
return (*it).second->name();
}
/// @brief looks up a collection by uuid
LogicalCollection* TRI_vocbase_t::lookupCollectionByUuid(std::string const& uuid) const {
// otherwise we'll look up the collection by name

View File

@ -168,8 +168,8 @@ struct TRI_vocbase_t {
std::unordered_map<std::string, arangodb::LogicalCollection*>
_collectionsByUuid; // collections by uuid
arangodb::basics::ReadWriteLock _viewsLock; // views management lock
std::atomic<std::thread::id> _viewsLockWriteOwner; // current thread owning '_viewsLock' write lock (workaround for non-recusrive ReadWriteLock)
mutable arangodb::basics::ReadWriteLock _viewsLock; // views management lock
mutable std::atomic<std::thread::id> _viewsLockWriteOwner; // current thread owning '_viewsLock' write lock (workaround for non-recusrive ReadWriteLock)
std::unordered_map<std::string, std::shared_ptr<arangodb::LogicalView>>
_viewsByName; // views by name
std::unordered_map<TRI_voc_cid_t, std::shared_ptr<arangodb::LogicalView>>
@ -279,6 +279,11 @@ struct TRI_vocbase_t {
/// returns empty string if the collection does not exist.
std::string collectionName(TRI_voc_cid_t id);
/// @brief get a view name by a view id
/// the name is fetched under a lock to make this thread-safe.
/// returns empty string if the view does not exist.
std::string viewName(TRI_voc_cid_t id) const;
/// @brief looks up a collection by uuid
arangodb::LogicalCollection* lookupCollectionByUuid(std::string const&) const;
/// @brief looks up a collection by name, identifier (cid) or uuid
@ -424,4 +429,4 @@ void TRI_SanitizeObject(arangodb::velocypack::Slice const slice,
void TRI_SanitizeObjectWithEdges(arangodb::velocypack::Slice const slice,
arangodb::velocypack::Builder& builder);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -867,14 +867,29 @@ TEST_CASE("IResearchQueryTestExists", "[iresearch][iresearch-query]") {
CHECK((i == expected.size()));
}
// bound view name is not supported
// test existent (bool) with bound view name
{
std::vector<arangodb::velocypack::Slice> expected = {
insertedDocs[1].slice(),
};
auto result = arangodb::tests::executeQuery(
vocbase,
"FOR d IN VIEW @@testView FILTER EXISTS(d.value, @type, 'bool') SORT BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d",
arangodb::velocypack::Parser::fromJson("{ \"type\" : \"type\", \"testView\": \"testView\" }")
arangodb::velocypack::Parser::fromJson("{ \"type\" : \"type\", \"@testView\": \"testView\" }")
);
REQUIRE(TRI_ERROR_QUERY_PARSE == result.code);
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 existent (bool) via []
@ -1286,4 +1301,4 @@ TEST_CASE("IResearchQueryTestExists", "[iresearch][iresearch-query]") {
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

View File

@ -369,6 +369,211 @@ TEST_CASE("IResearchQueryTestJoinVolatileBlock", "[iresearch][iresearch-query]")
// should not recreate iterator each loop iteration in case of deterministic/independent inner loop scope
}
TEST_CASE("IResearchQueryTestJoinDuplicateDataSource", "[iresearch][iresearch-query]") {
IResearchQuerySetup s;
UNUSED(s);
static std::vector<std::string> const EMPTY;
auto createJson = arangodb::velocypack::Parser::fromJson("{ \
\"name\": \"testView\", \
\"type\": \"arangosearch\" \
}");
TRI_vocbase_t vocbase(TRI_vocbase_type_e::TRI_VOCBASE_TYPE_NORMAL, 1, "testVocbase");
arangodb::LogicalCollection* logicalCollection1{};
arangodb::LogicalCollection* logicalCollection2{};
arangodb::LogicalCollection* logicalCollection3{};
arangodb::LogicalCollection* logicalCollectionWithTheSameNameAsView{};
// add collection_1
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"collection_1\" }");
logicalCollection1 = vocbase.createCollection(collectionJson->slice());
REQUIRE((nullptr != logicalCollection1));
}
// add collection_2
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"collection_2\" }");
logicalCollection2 = vocbase.createCollection(collectionJson->slice());
REQUIRE((nullptr != logicalCollection2));
}
// add collection_3
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"collection_3\" }");
logicalCollection3 = vocbase.createCollection(collectionJson->slice());
REQUIRE((nullptr != logicalCollection3));
}
// add logical collection with the same name as view
{
auto collectionJson = arangodb::velocypack::Parser::fromJson("{ \"name\": \"testView\" }");
logicalCollectionWithTheSameNameAsView = vocbase.createCollection(collectionJson->slice());
REQUIRE((nullptr != logicalCollectionWithTheSameNameAsView));
}
// add view
auto logicalView = vocbase.createView(createJson->slice(), 0);
REQUIRE((false == !logicalView));
auto* view = dynamic_cast<arangodb::iresearch::IResearchView*>(logicalView->getImplementation());
REQUIRE((false == !view));
// add link to collection
{
auto updateJson = arangodb::velocypack::Parser::fromJson(
"{ \"links\": {"
"\"collection_1\": { \"analyzers\": [ \"test_analyzer\", \"identity\" ], \"includeAllFields\": true, \"trackListPositions\": true },"
"\"collection_2\": { \"analyzers\": [ \"test_analyzer\", \"identity\" ], \"includeAllFields\": true }"
"}}"
);
CHECK((view->updateProperties(updateJson->slice(), true, false).ok()));
arangodb::velocypack::Builder builder;
builder.openObject();
view->getPropertiesVPack(builder, false);
builder.close();
auto slice = builder.slice();
auto tmpSlice = slice.get("links");
CHECK((true == tmpSlice.isObject() && 2 == tmpSlice.length()));
}
std::deque<arangodb::ManagedDocumentResult> insertedDocsView;
std::deque<arangodb::ManagedDocumentResult> insertedDocsCollectionWithTheSameNameAsView;
// populate view with the data
{
arangodb::OperationOptions opt;
TRI_voc_tick_t tick;
arangodb::transaction::UserTransaction trx(
arangodb::transaction::StandaloneContext::Create(&vocbase),
EMPTY, EMPTY, EMPTY,
arangodb::transaction::Options()
);
CHECK((trx.begin().ok()));
// insert into collections
{
irs::utf8_path resource;
resource/=irs::string_ref(IResearch_test_resource_dir);
resource/=irs::string_ref("simple_sequential.json");
auto builder = arangodb::basics::VelocyPackHelper::velocyPackFromFile(resource.utf8());
auto root = builder.slice();
REQUIRE(root.isArray());
size_t i = 0;
arangodb::LogicalCollection* collections[] {
logicalCollection1, logicalCollection2
};
for (auto doc : arangodb::velocypack::ArrayIterator(root)) {
insertedDocsView.emplace_back();
auto const res = collections[i % 2]->insert(&trx, doc, insertedDocsView.back(), opt, tick, false);
insertedDocsCollectionWithTheSameNameAsView.emplace_back();
logicalCollectionWithTheSameNameAsView->insert(&trx, doc, insertedDocsCollectionWithTheSameNameAsView.back(), opt, tick, false);
CHECK(res.ok());
++i;
}
}
// insert into collection_3
std::deque<arangodb::ManagedDocumentResult> insertedDocsCollection;
{
irs::utf8_path resource;
resource/=irs::string_ref(IResearch_test_resource_dir);
resource/=irs::string_ref("simple_sequential_order.json");
auto builder = arangodb::basics::VelocyPackHelper::velocyPackFromFile(resource.utf8());
auto root = builder.slice();
REQUIRE(root.isArray());
for (auto doc : arangodb::velocypack::ArrayIterator(root)) {
insertedDocsCollection.emplace_back();
auto const res = logicalCollection3->insert(&trx, doc, insertedDocsCollection.back(), opt, tick, false);
CHECK(res.ok());
}
}
CHECK((trx.commit().ok()));
view->sync();
}
// bind collection and view with the same name
{
std::string const query = "LET c=5 FOR x IN @@dataSource FILTER x.seq == c FOR d IN VIEW @@dataSource FILTER x.seq == d.seq RETURN x";
auto const boundParameters = arangodb::velocypack::Parser::fromJson("{ \"@dataSource\" : \"testView\" }");
CHECK(arangodb::tests::assertRules(
vocbase, query, {
arangodb::aql::OptimizerRule::handleViewsRule_pass6,
},
boundParameters
));
std::vector<arangodb::velocypack::Slice> expectedDocs {
arangodb::velocypack::Slice(insertedDocsCollectionWithTheSameNameAsView[5].vpack()),
};
auto queryResult = arangodb::tests::executeQuery(vocbase, query, boundParameters);
REQUIRE(TRI_ERROR_NO_ERROR == queryResult.code);
auto result = queryResult.result->slice();
CHECK(result.isArray());
arangodb::velocypack::ArrayIterator resultIt(result);
REQUIRE(expectedDocs.size() == resultIt.size());
// Check documents
auto expectedDoc = expectedDocs.begin();
for (;resultIt.valid(); resultIt.next(), ++expectedDoc) {
auto const actualDoc = resultIt.value();
auto const resolved = actualDoc.resolveExternals();
CHECK((0 == arangodb::basics::VelocyPackHelper::compare(arangodb::velocypack::Slice(*expectedDoc), resolved, true)));
}
CHECK(expectedDoc == expectedDocs.end());
}
// bind collection and view with the same name
//
// FIXME
// will not return any results because of the:
// https://github.com/arangodb/backlog/issues/342
{
std::string const query = "LET c=5 FOR x IN @@dataSource FILTER x.seq == c FOR d IN VIEW @@dataSource FILTER x.seq == d.seq RETURN d";
auto const boundParameters = arangodb::velocypack::Parser::fromJson("{ \"@dataSource\" : \"testView\" }");
CHECK(arangodb::tests::assertRules(
vocbase, query, {
arangodb::aql::OptimizerRule::handleViewsRule_pass6,
},
boundParameters
));
std::vector<arangodb::velocypack::Slice> expectedDocs {
arangodb::velocypack::Slice(insertedDocsCollectionWithTheSameNameAsView[5].vpack()),
};
auto queryResult = arangodb::tests::executeQuery(vocbase, query, boundParameters);
REQUIRE(TRI_ERROR_NO_ERROR == queryResult.code);
auto result = queryResult.result->slice();
CHECK(result.isArray());
arangodb::velocypack::ArrayIterator resultIt(result);
REQUIRE(0 == resultIt.size());
}
}
TEST_CASE("IResearchQueryTestJoin", "[iresearch][iresearch-query]") {
IResearchQuerySetup s;
UNUSED(s);
@ -1532,4 +1737,4 @@ TEST_CASE("IResearchQueryTestJoin", "[iresearch][iresearch-query]") {
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------