mirror of https://gitee.com/bigwinds/arangodb
fixed subquery nodes
This commit is contained in:
parent
92654e3d06
commit
f6dc5243ce
|
@ -92,7 +92,7 @@ void AstNode::toJson (TRI_json_t* json,
|
||||||
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateStringCopyJson(zone, "null"));
|
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateStringCopyJson(zone, "null"));
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_BOOL:
|
case VALUE_TYPE_BOOL:
|
||||||
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateStringCopyJson(zone, value.value._bool ? "true" : "false"));
|
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateBooleanJson(zone, value.value._bool));
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_INT:
|
case VALUE_TYPE_INT:
|
||||||
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateNumberJson(zone, static_cast<double>(value.value._int)));
|
TRI_Insert3ArrayJson(zone, node, "value", TRI_CreateNumberJson(zone, static_cast<double>(value.value._int)));
|
||||||
|
|
|
@ -49,7 +49,6 @@ Parser::Parser (Query* query)
|
||||||
_remainingLength(query->queryLength()),
|
_remainingLength(query->queryLength()),
|
||||||
_offset(0),
|
_offset(0),
|
||||||
_marker(nullptr),
|
_marker(nullptr),
|
||||||
_subQueryCount(0),
|
|
||||||
_uniqueId(0),
|
_uniqueId(0),
|
||||||
_stack() {
|
_stack() {
|
||||||
|
|
||||||
|
@ -87,7 +86,7 @@ bool Parser::configureWriteQuery (QueryType type,
|
||||||
TRI_ASSERT(type != AQL_QUERY_READ);
|
TRI_ASSERT(type != AQL_QUERY_READ);
|
||||||
|
|
||||||
// check if we currently are in a subquery
|
// check if we currently are in a subquery
|
||||||
if (isInSubQuery()) {
|
if (_ast->isInSubQuery()) {
|
||||||
// data modification not allowed in sub-queries
|
// data modification not allowed in sub-queries
|
||||||
registerError(TRI_ERROR_QUERY_MODIFY_IN_SUBQUERY);
|
registerError(TRI_ERROR_QUERY_MODIFY_IN_SUBQUERY);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -117,31 +117,6 @@ namespace triagens {
|
||||||
return _ast;
|
return _ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief start a subquery
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline void startSubQuery () {
|
|
||||||
++_subQueryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief end a subquery
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline void endSubQuery () {
|
|
||||||
TRI_ASSERT(_subQueryCount > 0);
|
|
||||||
--_subQueryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief whether or not we are in a subquery
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline bool isInSubQuery () const {
|
|
||||||
return (_subQueryCount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief return the scanner
|
/// @brief return the scanner
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -290,7 +265,6 @@ namespace triagens {
|
||||||
size_t _offset; // current parse position
|
size_t _offset; // current parse position
|
||||||
char const* _marker; // a position used temporarily during parsing
|
char const* _marker; // a position used temporarily during parsing
|
||||||
|
|
||||||
size_t _subQueryCount; // number of active subqueries
|
|
||||||
size_t _uniqueId; // a counter to generate unique (temporary) variable names
|
size_t _uniqueId; // a counter to generate unique (temporary) variable names
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ QueryAst::QueryAst (Query* query,
|
||||||
_bindParameters(),
|
_bindParameters(),
|
||||||
_collectionNames(),
|
_collectionNames(),
|
||||||
_root(nullptr),
|
_root(nullptr),
|
||||||
|
_queries(),
|
||||||
_writeCollection(nullptr),
|
_writeCollection(nullptr),
|
||||||
_writeOptions(nullptr) {
|
_writeOptions(nullptr) {
|
||||||
|
|
||||||
|
@ -71,7 +72,11 @@ QueryAst::QueryAst (Query* query,
|
||||||
TRI_ASSERT(_parser != nullptr);
|
TRI_ASSERT(_parser != nullptr);
|
||||||
|
|
||||||
_nodes.reserve(32);
|
_nodes.reserve(32);
|
||||||
_root = createNode(NODE_TYPE_ROOT);
|
_strings.reserve(32);
|
||||||
|
|
||||||
|
startSubQuery();
|
||||||
|
|
||||||
|
TRI_ASSERT(_root != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -496,14 +501,16 @@ AstNode* QueryAst::createNodeTernaryOperator (AstNode const* condition,
|
||||||
/// @brief create an AST subquery node
|
/// @brief create an AST subquery node
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AstNode* QueryAst::createNodeSubquery (char const* tempName) {
|
AstNode* QueryAst::createNodeSubquery (char const* variableName,
|
||||||
if (tempName == nullptr) {
|
AstNode const* subQuery) {
|
||||||
|
if (variableName == nullptr) {
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* node = createNode(NODE_TYPE_SUBQUERY);
|
AstNode* node = createNode(NODE_TYPE_SUBQUERY);
|
||||||
AstNode* variable = createNodeVariable(tempName, false);
|
AstNode* variable = createNodeVariable(variableName, false);
|
||||||
node->addMember(variable);
|
node->addMember(variable);
|
||||||
|
node->addMember(subQuery);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,57 @@ namespace triagens {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief begin a subquery
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void startSubQuery () {
|
||||||
|
// insert a new root node
|
||||||
|
AstNodeType type;
|
||||||
|
|
||||||
|
if (_queries.empty()) {
|
||||||
|
// root node of query
|
||||||
|
type = NODE_TYPE_ROOT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// sub query node
|
||||||
|
type = NODE_TYPE_SUBQUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto root = createNode(type);
|
||||||
|
|
||||||
|
// save the root node
|
||||||
|
_queries.push_back(root);
|
||||||
|
|
||||||
|
// set the current root node if everything went well
|
||||||
|
_root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief end a subquery
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AstNode* endSubQuery () {
|
||||||
|
// get the current root node
|
||||||
|
AstNode* root = _queries.back();
|
||||||
|
// remove it from the stack
|
||||||
|
_queries.pop_back();
|
||||||
|
|
||||||
|
// set root node to previous root node
|
||||||
|
_root = _queries.back();
|
||||||
|
|
||||||
|
// return the root node we just popped from the stack
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief whether or not we currently are in a subquery
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool isInSubQuery () const {
|
||||||
|
return (_queries.size() > 1);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief return a copy of our own bind parameters
|
/// @brief return a copy of our own bind parameters
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -297,7 +348,8 @@ namespace triagens {
|
||||||
/// @brief create an AST subquery node
|
/// @brief create an AST subquery node
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AstNode* createNodeSubquery (char const*);
|
AstNode* createNodeSubquery (char const*,
|
||||||
|
AstNode const*);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create an AST attribute access node
|
/// @brief create an AST attribute access node
|
||||||
|
@ -563,6 +615,12 @@ namespace triagens {
|
||||||
|
|
||||||
AstNode* _root;
|
AstNode* _root;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief root nodes of queries and subqueries
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<AstNode*> _queries;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief which collection is going to be modified in the query
|
/// @brief which collection is going to be modified in the query
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -434,16 +434,16 @@ expression:
|
||||||
}
|
}
|
||||||
| T_OPEN {
|
| T_OPEN {
|
||||||
parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_SUBQUERY);
|
parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_SUBQUERY);
|
||||||
parser->startSubQuery();
|
parser->ast()->startSubQuery();
|
||||||
} query T_CLOSE {
|
} query T_CLOSE {
|
||||||
parser->endSubQuery();
|
AstNode* node = parser->ast()->endSubQuery();
|
||||||
parser->ast()->scopes()->endCurrent();
|
parser->ast()->scopes()->endCurrent();
|
||||||
|
|
||||||
char const* tempName = parser->generateName();
|
char const* variableName = parser->generateName();
|
||||||
auto subQuery = parser->ast()->createNodeSubquery(tempName);
|
auto subQuery = parser->ast()->createNodeLet(variableName, node, false);
|
||||||
parser->ast()->addOperation(subQuery);
|
parser->ast()->addOperation(subQuery);
|
||||||
|
|
||||||
$$ = parser->ast()->createNodeReference(tempName);
|
$$ = parser->ast()->createNodeReference(variableName);
|
||||||
}
|
}
|
||||||
| operator_unary {
|
| operator_unary {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
|
Loading…
Reference in New Issue