1
0
Fork 0

resolve actual type of the data source on parsing instead of specifying type in `AstNode`

This commit is contained in:
Andrey Abramov 2018-03-08 23:44:49 +03:00
parent 33bc2f704f
commit c81cd02014
7 changed files with 973 additions and 978 deletions

View File

@ -38,6 +38,7 @@
#include "Transaction/Helpers.h" #include "Transaction/Helpers.h"
#include "Utils/CollectionNameResolver.h" #include "Utils/CollectionNameResolver.h"
#include "VocBase/LogicalCollection.h" #include "VocBase/LogicalCollection.h"
#include "VocBase/LogicalView.h"
#include <velocypack/Iterator.h> #include <velocypack/Iterator.h>
#include <velocypack/Slice.h> #include <velocypack/Slice.h>
@ -586,7 +587,6 @@ AstNode* Ast::createNodeCollection(char const* name,
AstNode* node = createNode(NODE_TYPE_COLLECTION); AstNode* node = createNode(NODE_TYPE_COLLECTION);
node->setStringValue(name, strlen(name)); node->setStringValue(name, strlen(name));
node->dataSourceType = AstNode::DataSourceType::Collection;
_query->collections()->add(name, accessType); _query->collections()->add(name, accessType);
@ -621,7 +621,6 @@ AstNode* Ast::createNodeView(char const* name) {
AstNode* node = createNode(NODE_TYPE_VIEW); AstNode* node = createNode(NODE_TYPE_VIEW);
node->setStringValue(name, strlen(name)); node->setStringValue(name, strlen(name));
node->dataSourceType = AstNode::DataSourceType::View;
auto* collections = _query->collections(); auto* collections = _query->collections();
@ -682,8 +681,7 @@ AstNode* Ast::createNodeReference(Variable const* variable) {
/// @brief create an AST parameter node /// @brief create an AST parameter node
AstNode* Ast::createNodeParameter( AstNode* Ast::createNodeParameter(
char const* name, char const* name,
size_t length, size_t length
AstNode::DataSourceType dataSourceType /* = AstNode::DataSourceType::Invalid */
) { ) {
if (name == nullptr) { if (name == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
@ -692,7 +690,6 @@ AstNode* Ast::createNodeParameter(
AstNode* node = createNode(NODE_TYPE_PARAMETER); AstNode* node = createNode(NODE_TYPE_PARAMETER);
node->setStringValue(name, length); node->setStringValue(name, length);
node->dataSourceType = dataSourceType;
// insert bind parameter name into list of found parameters // insert bind parameter name into list of found parameters
_bindParameters.emplace(name); _bindParameters.emplace(name);
@ -1425,11 +1422,37 @@ void Ast::injectBindParameters(BindParameters& parameters) {
TRI_ASSERT(!param.empty()); TRI_ASSERT(!param.empty());
switch (node->getDataSourceType()) { if ('@' == param[0]) {
case AstNode::DataSourceType::Collection: { // bound data source parameter
// bound collection parameter
TRI_ASSERT(value.isString()); TRI_ASSERT(value.isString());
char const* name = nullptr;
VPackValueLength length;
char const* stringValue = value.getString(length);
// FIXME use external resolver
arangodb::CollectionNameResolver resolver(_query->vocbase());
std::shared_ptr<LogicalDataSource> dataSource;
if (length > 0 && stringValue[0] >= '0' && stringValue[0] <= '9') {
dataSource = resolver.getDataSource(basics::StringUtils::uint64(stringValue, length));
} else {
dataSource = resolver.getDataSource(std::string(stringValue, length));
}
if (!dataSource) {
// FIXME use TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND
THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
value.copyString().c_str()
);
}
// TODO: can we get away without registering the string value here?
auto& dataSourceName = dataSource->name();
name = _query->registerString(dataSourceName.c_str(), dataSourceName.size());
if (LogicalCollection::category() == dataSource->category()) {
// check if the collection was used in a data-modification query // check if the collection was used in a data-modification query
bool isWriteCollection = false; bool isWriteCollection = false;
@ -1440,28 +1463,6 @@ void Ast::injectBindParameters(BindParameters& parameters) {
} }
} }
// 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 node = createNodeCollection(name, isWriteCollection
? AccessMode::Type::WRITE ? AccessMode::Type::WRITE
: AccessMode::Type::READ); : AccessMode::Type::READ);
@ -1477,36 +1478,15 @@ void Ast::injectBindParameters(BindParameters& parameters) {
} }
} }
} }
} break; } else if (LogicalView::category() == dataSource->category()) {
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); node = createNodeView(name);
} break; } else {
default: { THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_INTERNAL,
"unexpected data source category"
);
}
} else {
// regular bound parameter // regular bound parameter
node = nodeFromVPack(value, true); node = nodeFromVPack(value, true);
@ -1524,7 +1504,6 @@ void Ast::injectBindParameters(BindParameters& parameters) {
// finally note that the node was created from a bind parameter // finally note that the node was created from a bind parameter
node->setFlag(FLAG_BIND_PARAMETER); node->setFlag(FLAG_BIND_PARAMETER);
} break;
} }
} }
} else if (node->type == NODE_TYPE_BOUND_ATTRIBUTE_ACCESS) { } else if (node->type == NODE_TYPE_BOUND_ATTRIBUTE_ACCESS) {

View File

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

View File

@ -202,12 +202,6 @@ static_assert(NODE_TYPE_ARRAY < NODE_TYPE_OBJECT, "incorrect node types order");
struct AstNode { struct AstNode {
friend class Ast; 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 Operators;
static std::unordered_map<int, std::string const> const TypeNames; static std::unordered_map<int, std::string const> const TypeNames;
static std::unordered_map<int, std::string const> const ValueTypeNames; static std::unordered_map<int, std::string const> const ValueTypeNames;
@ -395,10 +389,6 @@ struct AstNode {
} }
} }
inline DataSourceType getDataSourceType() const noexcept {
return dataSourceType;
}
/// @brief whether or not a value node is of type attribute access that /// @brief whether or not a value node is of type attribute access that
/// refers to a variable reference /// refers to a variable reference
AstNode const* getAttributeAccessForVariable(bool allowIndexedAccess) const { AstNode const* getAttributeAccessForVariable(bool allowIndexedAccess) const {
@ -738,14 +728,9 @@ struct AstNode {
AstNodeValue value; AstNodeValue value;
private: private:
union {
/// @brief precomputed VPack value (used when executing expressions) /// @brief precomputed VPack value (used when executing expressions)
uint8_t mutable* computedValue; uint8_t mutable* computedValue;
/// @brief type of the data source
DataSourceType dataSourceType;
};
/// @brief the node's sub nodes /// @brief the node's sub nodes
std::vector<AstNode*> members; std::vector<AstNode*> members;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -331,7 +331,6 @@ static AstNode const* GetIntoExpression(AstNode const* node) {
%type <node> view_name; %type <node> view_name;
%type <node> in_or_into_collection; %type <node> in_or_into_collection;
%type <node> bind_parameter; %type <node> bind_parameter;
%type <node> bind_view;
%type <strval> variable_name; %type <strval> variable_name;
%type <node> numeric_value; %type <node> numeric_value;
%type <intval> update_or_replace; %type <intval> update_or_replace;
@ -1690,8 +1689,12 @@ view_name:
| T_QUOTED_STRING { | T_QUOTED_STRING {
$$ = parser->ast()->createNodeView($1.value); $$ = parser->ast()->createNodeView($1.value);
} }
| bind_view { | T_DATA_SOURCE_PARAMETER {
$$ = $1; 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);
} }
; ;
@ -1701,23 +1704,13 @@ bind_parameter:
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->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); $$ = parser->ast()->createNodeParameter($1.value, $1.length);
} }
| T_PARAMETER { | T_PARAMETER {
$$ = parser->ast()->createNodeParameter($1.value, $1.length); $$ = 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: object_element_name:
T_STRING { T_STRING {
$$ = $1; $$ = $1;

View File

@ -331,16 +331,14 @@ std::shared_ptr<LogicalDataSource> CollectionNameResolver::getDataSource(
} }
try { try {
auto name = std::to_string(id); auto const name = std::to_string(id);
auto cinfo = ci->getCollection(_vocbase->name(), name); auto cinfo = ci->getCollection(_vocbase->name(), name);
if (cinfo) { if (cinfo) {
return std::static_pointer_cast<LogicalDataSource>(cinfo); return cinfo;
} }
return std::static_pointer_cast<LogicalDataSource>( return ci->getView(_vocbase->name(), name);
ci->getView(_vocbase->name(), name)
);
} catch (...) { } catch (...) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) LOG_TOPIC(ERR, arangodb::Logger::FIXME)
<< "caught exception while resolving cluster data-source id: " << id; << "caught exception while resolving cluster data-source id: " << id;
@ -349,6 +347,38 @@ std::shared_ptr<LogicalDataSource> CollectionNameResolver::getDataSource(
return nullptr; return nullptr;
} }
std::shared_ptr<LogicalDataSource> CollectionNameResolver::getDataSource(
std::string const& name
) const noexcept {
// db server / standalone
if (!ServerState::isRunningInCluster(_serverRole)
|| ServerState::isDBServer(_serverRole)) {
return _vocbase ? _vocbase->lookupDataSource(name) : nullptr;
}
// cluster coordinator
auto* ci = ClusterInfo::instance();
if (!ci) {
return nullptr;
}
try {
auto cinfo = ci->getCollection(_vocbase->name(), name);
if (cinfo) {
return cinfo;
}
return ci->getView(_vocbase->name(), name);
} catch (...) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
<< "caught exception while resolving cluster data-source name: " << name;
}
return nullptr;
}
std::string CollectionNameResolver::getViewNameCluster( std::string CollectionNameResolver::getViewNameCluster(
TRI_voc_cid_t cid TRI_voc_cid_t cid
) const { ) const {

View File

@ -122,12 +122,19 @@ class CollectionNameResolver {
std::string getCollectionName(std::string const& nameOrId) const; std::string getCollectionName(std::string const& nameOrId) const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief look up a collection struct for a collection name /// @brief look up a data source struct for an identifier
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
std::shared_ptr<LogicalDataSource> getDataSource( std::shared_ptr<LogicalDataSource> getDataSource(
TRI_voc_cid_t id TRI_voc_cid_t id
) const noexcept; ) const noexcept;
//////////////////////////////////////////////////////////////////////////////
/// @brief look up a data source struct for a name
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<LogicalDataSource> getDataSource(
std::string const& name
) const noexcept;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief look up a cluster-wide view name for a cluster-wide view id /// @brief look up a cluster-wide view name for a cluster-wide view id
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////