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 "Utils/CollectionNameResolver.h"
#include "VocBase/LogicalCollection.h"
#include "VocBase/LogicalView.h"
#include <velocypack/Iterator.h>
#include <velocypack/Slice.h>
@ -586,7 +587,6 @@ 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);
@ -621,7 +621,6 @@ 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();
@ -682,8 +681,7 @@ AstNode* Ast::createNodeReference(Variable const* variable) {
/// @brief create an AST parameter node
AstNode* Ast::createNodeParameter(
char const* name,
size_t length,
AstNode::DataSourceType dataSourceType /* = AstNode::DataSourceType::Invalid */
size_t length
) {
if (name == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
@ -692,7 +690,6 @@ AstNode* Ast::createNodeParameter(
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);
@ -1425,107 +1422,89 @@ void Ast::injectBindParameters(BindParameters& parameters) {
TRI_ASSERT(!param.empty());
switch (node->getDataSourceType()) {
case AstNode::DataSourceType::Collection: {
// bound collection parameter
if ('@' == param[0]) {
// bound data source parameter
TRI_ASSERT(value.isString());
// check if the collection was used in a data-modification query
bool isWriteCollection = false;
for (auto const& it : _writeCollections) {
if (it->type == NODE_TYPE_PARAMETER && StringRef(param) == StringRef(it->getStringValue(), it->getStringLength())) {
isWriteCollection = true;
break;
}
}
// 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());
}
// FIXME use external resolver
arangodb::CollectionNameResolver resolver(_query->vocbase());
std::shared_ptr<LogicalDataSource> dataSource;
name = _query->registerString(collectionName.c_str(), collectionName.size());
if (length > 0 && stringValue[0] >= '0' && stringValue[0] <= '9') {
dataSource = resolver.getDataSource(basics::StringUtils::uint64(stringValue, length));
} else {
// TODO: can we get away without registering the string value here?
name = _query->registerString(stringValue, static_cast<size_t>(length));
dataSource = resolver.getDataSource(std::string(stringValue, length));
}
TRI_ASSERT(name != nullptr);
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()
);
}
node = createNodeCollection(name, isWriteCollection
// 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
bool isWriteCollection = false;
for (auto const& it : _writeCollections) {
if (it->type == NODE_TYPE_PARAMETER && StringRef(param) == StringRef(it->getStringValue(), it->getStringLength())) {
isWriteCollection = true;
break;
}
}
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
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 if (LogicalView::category() == dataSource->category()) {
node = createNodeView(name);
} else {
// TODO: can we get away without registering the string value here?
name = _query->registerString(stringValue, static_cast<size_t>(length));
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_INTERNAL,
"unexpected data source category"
);
}
} else {
// regular bound parameter
node = nodeFromVPack(value, true);
TRI_ASSERT(name != nullptr);
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);
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;
}
// finally note that the node was created from a bind parameter
node->setFlag(FLAG_BIND_PARAMETER);
}
}
} else if (node->type == NODE_TYPE_BOUND_ATTRIBUTE_ACCESS) {
// look at second sub-node. this is the (replaced) bind parameter

View File

@ -238,8 +238,7 @@ class Ast {
/// @brief create an AST parameter node
AstNode* createNodeParameter(
char const* name,
size_t length,
AstNode::DataSourceType dataSourceType = AstNode::DataSourceType::Invalid
size_t length
);
/// @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 {
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;
@ -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
/// refers to a variable reference
AstNode const* getAttributeAccessForVariable(bool allowIndexedAccess) const {
@ -738,13 +728,8 @@ struct AstNode {
AstNodeValue value;
private:
union {
/// @brief precomputed VPack value (used when executing expressions)
uint8_t mutable* computedValue;
/// @brief type of the data source
DataSourceType dataSourceType;
};
/// @brief precomputed VPack value (used when executing expressions)
uint8_t mutable* computedValue;
/// @brief the node's sub nodes
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> 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;
@ -1690,8 +1689,12 @@ view_name:
| T_QUOTED_STRING {
$$ = parser->ast()->createNodeView($1.value);
}
| bind_view {
$$ = $1;
| 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);
}
;
@ -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->ast()->createNodeParameter($1.value, $1.length, AstNode::DataSourceType::Collection);
$$ = parser->ast()->createNodeParameter($1.value, $1.length);
}
| 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

@ -331,16 +331,14 @@ std::shared_ptr<LogicalDataSource> CollectionNameResolver::getDataSource(
}
try {
auto name = std::to_string(id);
auto const name = std::to_string(id);
auto cinfo = ci->getCollection(_vocbase->name(), name);
if (cinfo) {
return std::static_pointer_cast<LogicalDataSource>(cinfo);
return cinfo;
}
return std::static_pointer_cast<LogicalDataSource>(
ci->getView(_vocbase->name(), name)
);
return ci->getView(_vocbase->name(), name);
} catch (...) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
<< "caught exception while resolving cluster data-source id: " << id;
@ -349,6 +347,38 @@ std::shared_ptr<LogicalDataSource> CollectionNameResolver::getDataSource(
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(
TRI_voc_cid_t cid
) const {

View File

@ -122,12 +122,19 @@ class CollectionNameResolver {
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(
TRI_voc_cid_t id
) 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
//////////////////////////////////////////////////////////////////////////////
@ -176,4 +183,4 @@ class CollectionNameResolver {
};
}
#endif
#endif