mirror of https://gitee.com/bigwinds/arangodb
fixed creation of subqueries from JSON input
This commit is contained in:
parent
f179c35f02
commit
99ce138c12
|
@ -416,7 +416,7 @@ AstNode* Ast::createNodeReference (char const* variableName) {
|
|||
auto variable = _scopes.getVariable(variableName);
|
||||
|
||||
if (variable == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "variable not found in reference AstNode");
|
||||
}
|
||||
|
||||
node->setData(variable);
|
||||
|
@ -1268,7 +1268,7 @@ AstNode* Ast::optimizeBinaryOperatorArithmetic (AstNode* node) {
|
|||
value = fmod(l, r);
|
||||
}
|
||||
else {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid operator");
|
||||
}
|
||||
|
||||
if (value != value ||
|
||||
|
@ -1516,7 +1516,7 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) {
|
|||
TRI_json_t const* value = static_cast<TRI_json_t const*>(TRI_AtVector(&json->_value._objects, i + 1));
|
||||
|
||||
if (! TRI_IsStringJson(key) || value == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected type found in array node");
|
||||
}
|
||||
|
||||
char const* attributeName = _query->registerString(key->_value._string.data, key->_value._string.length - 1, false);
|
||||
|
|
|
@ -521,10 +521,15 @@ bool AstNode::isSimple () const {
|
|||
if (type == NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||
TRI_ASSERT(numMembers() == 1);
|
||||
|
||||
auto member = getMember(0);
|
||||
return member->isSimple();
|
||||
return getMember(0)->isSimple();
|
||||
}
|
||||
/*
|
||||
if (type == NODE_TYPE_INDEXED_ACCESS) {
|
||||
TRI_ASSERT(numMembers() == 2);
|
||||
|
||||
return (getMember(0)->isSimple() && getMember(1)->isSimple());
|
||||
}
|
||||
*/
|
||||
if (type == NODE_TYPE_REFERENCE) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -84,12 +84,9 @@ void ExecutionNode::validateType (int type) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
ExecutionNode* ExecutionNode::fromJsonFactory (Ast const* ast,
|
||||
const Json &oneNode)
|
||||
{
|
||||
const Json &oneNode) {
|
||||
auto JsonString = oneNode.toString();
|
||||
std::cout << "XX>" << JsonString << "<-\n";
|
||||
|
||||
int nodeTypeID = JsonHelper::getNumericValue<int>(oneNode.json(), "typeID", 0);
|
||||
triagens::aql::Query* query = ast->query();
|
||||
|
@ -97,118 +94,103 @@ ExecutionNode* ExecutionNode::fromJsonFactory (Ast const* ast,
|
|||
|
||||
NodeType nodeType = (NodeType) nodeTypeID;
|
||||
switch (nodeType) {
|
||||
case SINGLETON:
|
||||
return new SingletonNode(query, oneNode);
|
||||
case ENUMERATE_COLLECTION:
|
||||
return new EnumerateCollectionNode(query, oneNode);
|
||||
case ENUMERATE_LIST:
|
||||
return new EnumerateListNode(query, oneNode);
|
||||
case FILTER:
|
||||
return new FilterNode(query, oneNode);
|
||||
case LIMIT:
|
||||
return new LimitNode(query, oneNode);
|
||||
case CALCULATION:
|
||||
return new CalculationNode(query, oneNode);
|
||||
case SUBQUERY: {
|
||||
auto JsonString = oneNode.toString();
|
||||
std::cout << "1>" << JsonString << "<-\n";
|
||||
auto subquery=oneNode.get("subquery");
|
||||
JsonString = subquery.toString();
|
||||
std::cout << "2>" << JsonString << "<-\n";
|
||||
auto subsubquery=subquery.get("nodes");
|
||||
JsonString = subsubquery.toString();
|
||||
std::cout << "3>" << JsonString << "<-\n";
|
||||
case SINGLETON:
|
||||
return new SingletonNode(query, oneNode);
|
||||
case ENUMERATE_COLLECTION:
|
||||
return new EnumerateCollectionNode(query, oneNode);
|
||||
case ENUMERATE_LIST:
|
||||
return new EnumerateListNode(query, oneNode);
|
||||
case FILTER:
|
||||
return new FilterNode(query, oneNode);
|
||||
case LIMIT:
|
||||
return new LimitNode(query, oneNode);
|
||||
case CALCULATION:
|
||||
return new CalculationNode(query, oneNode);
|
||||
case SUBQUERY:
|
||||
return new SubqueryNode(ast, query, oneNode);
|
||||
case SORT: {
|
||||
Json jsonElements = oneNode.get("elements");
|
||||
if (! jsonElements.isList()){
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected value for SortNode elements");
|
||||
}
|
||||
size_t len = jsonElements.size();
|
||||
std::vector<std::pair<Variable const*, bool>> elements;
|
||||
elements.reserve(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
Json oneJsonElement = jsonElements.at(i);
|
||||
bool ascending = JsonHelper::getBooleanValue(oneJsonElement.json(), "ascending", false);
|
||||
Variable *v = query->registerVar(new Variable(oneJsonElement.get("inVariable")));
|
||||
elements.push_back(std::make_pair(v, ascending));
|
||||
}
|
||||
|
||||
|
||||
auto totalsubquery=oneNode.get("subquery").get("nodes");
|
||||
JsonString = totalsubquery.toString();
|
||||
std::cout << "4>" << JsonString << "<-\n";
|
||||
|
||||
return new SubqueryNode(ast, query, oneNode);
|
||||
}
|
||||
case SORT: {
|
||||
Json jsonElements = oneNode.get("elements");
|
||||
if (!jsonElements.isList()){
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "missing node type in valueTypeNames"); //// TODO
|
||||
return new SortNode(query, oneNode, elements);
|
||||
}
|
||||
int len = jsonElements.size();
|
||||
std::vector<std::pair<Variable const*, bool>> elements;
|
||||
elements.reserve(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json oneJsonElement = jsonElements.at(i);
|
||||
bool ascending = JsonHelper::getBooleanValue(oneJsonElement.json(), "ascending", false);
|
||||
Variable *v = query->registerVar(new Variable(oneJsonElement.get("inVariable")));
|
||||
elements.push_back(std::make_pair(v, ascending));
|
||||
case AGGREGATE: {
|
||||
|
||||
Json outVariableJson = oneNode.get("outVariable");
|
||||
Variable *outVariable = nullptr;
|
||||
|
||||
if (!outVariableJson.isEmpty()) /* Optional... */
|
||||
outVariable = query->registerVar(new Variable(outVariableJson));
|
||||
|
||||
|
||||
Json jsonAaggregates = oneNode.get("aggregates");
|
||||
if (!jsonAaggregates.isList()){
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "missing node type in valueTypeNames"); //// TODO
|
||||
}
|
||||
|
||||
int len = jsonAaggregates.size();
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables;
|
||||
|
||||
aggregateVariables.reserve(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json oneJsonAggregate = jsonAaggregates.at(i);
|
||||
Variable* outVariable = query->registerVar(new Variable(oneJsonAggregate.get("outVariable")));
|
||||
Variable* inVariable = query->registerVar(new Variable(oneJsonAggregate.get("inVariable")));
|
||||
|
||||
aggregateVariables.push_back(std::make_pair(outVariable, inVariable));
|
||||
}
|
||||
|
||||
return new AggregateNode(query,
|
||||
oneNode,
|
||||
outVariable,
|
||||
ast->variables()->variables(false),
|
||||
aggregateVariables);
|
||||
}
|
||||
|
||||
return new SortNode(query, oneNode, elements);
|
||||
}
|
||||
case AGGREGATE: {
|
||||
|
||||
Json outVariableJson = oneNode.get("outVariable");
|
||||
Variable *outVariable = nullptr;
|
||||
|
||||
if (!outVariableJson.isEmpty()) /* Optional... */
|
||||
outVariable = query->registerVar(new Variable(outVariableJson));
|
||||
|
||||
|
||||
Json jsonAaggregates = oneNode.get("aggregates");
|
||||
if (!jsonAaggregates.isList()){
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "missing node type in valueTypeNames"); //// TODO
|
||||
}
|
||||
|
||||
int len = jsonAaggregates.size();
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables;
|
||||
|
||||
aggregateVariables.reserve(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Json oneJsonAggregate = jsonAaggregates.at(i);
|
||||
Variable* outVariable = query->registerVar(new Variable(oneJsonAggregate.get("outVariable")));
|
||||
Variable* inVariable = query->registerVar(new Variable(oneJsonAggregate.get("inVariable")));
|
||||
|
||||
aggregateVariables.push_back(std::make_pair(outVariable, inVariable));
|
||||
}
|
||||
|
||||
return new AggregateNode(query,
|
||||
oneNode,
|
||||
outVariable,
|
||||
ast->variables()->variables(false),
|
||||
aggregateVariables);
|
||||
}
|
||||
case INSERT:
|
||||
return new InsertNode(query, oneNode);
|
||||
case REMOVE:
|
||||
return new RemoveNode(query, oneNode);
|
||||
case REPLACE:
|
||||
return new ReplaceNode(query, oneNode);
|
||||
case UPDATE:
|
||||
return new UpdateNode(query, oneNode);
|
||||
case RETURN:
|
||||
return new ReturnNode(query, oneNode);
|
||||
case INTERSECTION:
|
||||
//return new (query, oneNode);
|
||||
case PROJECTION:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_JOIN:
|
||||
//return new (query, oneNode);
|
||||
case MERGE_JOIN:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_INDEX_UNIQUE:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_INDEX_RANGE:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_FULL_COLLECTION:
|
||||
//return new (query, oneNode);
|
||||
case CONCATENATION:
|
||||
//return new (query, oneNode);
|
||||
case INDEX_RANGE:
|
||||
//return new (query, oneNode);
|
||||
case MERGE:
|
||||
//return new (query, oneNode);
|
||||
case REMOTE:
|
||||
//return new (query, oneNode);
|
||||
case ILLEGAL:
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
case INSERT:
|
||||
return new InsertNode(query, oneNode);
|
||||
case REMOVE:
|
||||
return new RemoveNode(query, oneNode);
|
||||
case REPLACE:
|
||||
return new ReplaceNode(query, oneNode);
|
||||
case UPDATE:
|
||||
return new UpdateNode(query, oneNode);
|
||||
case RETURN:
|
||||
return new ReturnNode(query, oneNode);
|
||||
case INTERSECTION:
|
||||
//return new (query, oneNode);
|
||||
case PROJECTION:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_JOIN:
|
||||
//return new (query, oneNode);
|
||||
case MERGE_JOIN:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_INDEX_UNIQUE:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_INDEX_RANGE:
|
||||
//return new (query, oneNode);
|
||||
case LOOKUP_FULL_COLLECTION:
|
||||
//return new (query, oneNode);
|
||||
case CONCATENATION:
|
||||
//return new (query, oneNode);
|
||||
case INDEX_RANGE:
|
||||
//return new (query, oneNode);
|
||||
case MERGE:
|
||||
//return new (query, oneNode);
|
||||
case REMOTE:
|
||||
//return new (query, oneNode);
|
||||
case ILLEGAL:
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled node type");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -218,12 +200,11 @@ ExecutionNode* ExecutionNode::fromJsonFactory (Ast const* ast,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Json ExecutionNode::toJson (TRI_memory_zone_t* zone) {
|
||||
std::map<ExecutionNode*, int> indexTab;
|
||||
Json json;
|
||||
Json nodes;
|
||||
try {
|
||||
nodes = Json(Json::List, 10);
|
||||
toJsonHelper(indexTab, nodes, zone);
|
||||
toJsonHelper(nodes, zone);
|
||||
json = Json(Json::Array, 1)
|
||||
("nodes", nodes);
|
||||
}
|
||||
|
@ -299,36 +280,28 @@ void ExecutionNode::walk (WalkerWorker<ExecutionNode>* worker) {
|
|||
/// @brief toJsonHelper, for a generic node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Json ExecutionNode::toJsonHelperGeneric (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
Json ExecutionNode::toJsonHelperGeneric (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
auto iter = indexTab.find(this);
|
||||
if (iter != indexTab.end()) {
|
||||
return Json();
|
||||
size_t const n = _dependencies.size();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
_dependencies[i]->toJsonHelper(nodes, zone);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _dependencies.size(); i++) {
|
||||
_dependencies[i]->toJsonHelper(indexTab, nodes, zone);
|
||||
}
|
||||
Json json;
|
||||
json = Json(Json::Array, 2)
|
||||
("type", Json(getTypeString()));
|
||||
json ("typeID", Json(static_cast<int>(getType())));
|
||||
Json deps(Json::List, _dependencies.size());
|
||||
for (size_t i = 0; i < _dependencies.size(); i++) {
|
||||
auto it = indexTab.find(_dependencies[i]);
|
||||
if (it != indexTab.end()) {
|
||||
deps(Json(static_cast<double>(it->second)));
|
||||
}
|
||||
else {
|
||||
deps(Json("unknown"));
|
||||
}
|
||||
Json deps(Json::List, n);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
deps(Json(static_cast<double>(_dependencies[i]->id())));
|
||||
}
|
||||
json("dependencies", deps);
|
||||
json("index", Json(static_cast<double>(nodes.size())));
|
||||
json("id", Json(static_cast<double>(id())));
|
||||
|
||||
if(this->_estimatedCost != 0){
|
||||
json("estimatedCost", Json(this->_estimatedCost));
|
||||
}
|
||||
/*
|
||||
if (_varUsageValid) {
|
||||
Json varsValid(Json::List, _varsValid.size());
|
||||
for (auto v : _varsValid) {
|
||||
|
@ -341,7 +314,7 @@ Json ExecutionNode::toJsonHelperGeneric (std::map<ExecutionNode*, int>& indexTab
|
|||
}
|
||||
json("varsUsedLater", varsUsedLater);
|
||||
}
|
||||
|
||||
*/
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -377,32 +350,32 @@ void ExecutionNode::fromJsonHelper (triagens::aql::Query* q, basics::Json const&
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief toJson, for SingletonNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
SingletonNode::SingletonNode (triagens::aql::Query* query, basics::Json const& base) {
|
||||
|
||||
SingletonNode::SingletonNode (triagens::aql::Query* query, basics::Json const& base)
|
||||
: ExecutionNode(base) {
|
||||
fromJsonHelper(query, base);
|
||||
}
|
||||
|
||||
void SingletonNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void SingletonNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- methods of EnumerateCollectionNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
EnumerateCollectionNode::EnumerateCollectionNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: _vocbase(q->vocbase()),
|
||||
: ExecutionNode(base),
|
||||
_vocbase(q->vocbase()),
|
||||
_collection(q->collections()->get(JsonHelper::getStringValue(base.json(), "collection", ""))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable"))))
|
||||
{
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -410,10 +383,9 @@ EnumerateCollectionNode::EnumerateCollectionNode (triagens::aql::Query* q, basic
|
|||
/// @brief toJson, for EnumerateCollectionNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EnumerateCollectionNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void EnumerateCollectionNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -425,19 +397,17 @@ void EnumerateCollectionNode::toJsonHelper (std::map<ExecutionNode*, int>& index
|
|||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- methods of EnumerateListNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
EnumerateListNode::EnumerateListNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: _inVariable(q->registerVar(new Variable(base.get("inVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable"))))
|
||||
{
|
||||
///TODO
|
||||
: ExecutionNode(base),
|
||||
_inVariable(q->registerVar(new Variable(base.get("inVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -445,10 +415,9 @@ EnumerateListNode::EnumerateListNode (triagens::aql::Query* q, basics::Json cons
|
|||
/// @brief toJson, for EnumerateListNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EnumerateListNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void EnumerateListNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -456,20 +425,17 @@ void EnumerateListNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief toJson, for IndexRangeNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IndexRangeNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void IndexRangeNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone));
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone));
|
||||
// call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
|
@ -497,16 +463,15 @@ void IndexRangeNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
("ranges", ranges);
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- methods of LimitNode
|
||||
// -----------------------------------------------------------------------------
|
||||
LimitNode::LimitNode (triagens::aql::Query* query, basics::Json const& base) {
|
||||
///TODO
|
||||
|
||||
LimitNode::LimitNode (triagens::aql::Query* query, basics::Json const& base)
|
||||
: ExecutionNode(base) {
|
||||
_offset = JsonHelper::getNumericValue<double>(base.json(), "offset", 0.0);
|
||||
_limit = JsonHelper::getNumericValue<double>(base.json(), "limit", 0.0);
|
||||
fromJsonHelper(query, base);
|
||||
|
@ -516,10 +481,9 @@ LimitNode::LimitNode (triagens::aql::Query* query, basics::Json const& base) {
|
|||
/// @brief toJson, for LimitNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LimitNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void LimitNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -528,9 +492,7 @@ void LimitNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
("limit", Json(static_cast<double>(_limit)));
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -538,11 +500,10 @@ void LimitNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
CalculationNode::CalculationNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: _expression(new Expression(q, base)),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable"))))
|
||||
{
|
||||
: ExecutionNode(base),
|
||||
_expression(new Expression(q, base)),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
//// _expression->fromJson(base, "expression")) -> list -> for schleife.
|
||||
///TODO
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -550,10 +511,9 @@ CalculationNode::CalculationNode (triagens::aql::Query* q, basics::Json const& b
|
|||
/// @brief toJson, for CalculationNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CalculationNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void CalculationNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -564,9 +524,7 @@ void CalculationNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -576,10 +534,9 @@ void CalculationNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
SubqueryNode::SubqueryNode (Ast const* ast,
|
||||
triagens::aql::Query* q,
|
||||
basics::Json const& base)
|
||||
: _outVariable(q->registerVar(new Variable(base.get("outVariable"))))
|
||||
{
|
||||
/// _subquery(ExecutionNode::fromJsonFactory(ast, base.get("subquery").get("nodes"))),
|
||||
///TODO
|
||||
: ExecutionNode(base),
|
||||
_subquery(nullptr),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -587,10 +544,9 @@ SubqueryNode::SubqueryNode (Ast const* ast,
|
|||
/// @brief toJson, for SubqueryNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SubqueryNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void SubqueryNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -598,9 +554,7 @@ void SubqueryNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -672,8 +626,8 @@ std::vector<Variable const*> SubqueryNode::getVariablesUsedHere () {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
FilterNode::FilterNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: _inVariable(q->registerVar(new Variable(base.get("inVariable")))) {
|
||||
///TODO
|
||||
: ExecutionNode(base),
|
||||
_inVariable(q->registerVar(new Variable(base.get("inVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -681,10 +635,9 @@ FilterNode::FilterNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson, for FilterNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FilterNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void FilterNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -692,9 +645,7 @@ void FilterNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
json("inVariable", _inVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -704,8 +655,8 @@ void FilterNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
SortNode::SortNode (triagens::aql::Query* query,
|
||||
basics::Json const& base,
|
||||
std::vector<std::pair<Variable const*, bool>> elements)
|
||||
: _elements(elements) {
|
||||
///TODO
|
||||
: ExecutionNode(base),
|
||||
_elements(elements) {
|
||||
fromJsonHelper(query, base);
|
||||
}
|
||||
|
||||
|
@ -713,10 +664,9 @@ SortNode::SortNode (triagens::aql::Query* query,
|
|||
/// @brief toJson, for SortNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SortNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void SortNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -730,9 +680,7 @@ void SortNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
json("elements", values);
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -744,11 +692,10 @@ AggregateNode::AggregateNode (triagens::aql::Query* q,
|
|||
Variable const* outVariable,
|
||||
std::unordered_map<VariableId, std::string const> const& variableMap,
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables)
|
||||
: _aggregateVariables(aggregateVariables),///TODO: aggregates belong to this object?
|
||||
: ExecutionNode(base),
|
||||
_aggregateVariables(aggregateVariables),
|
||||
_outVariable(outVariable),
|
||||
_variableMap(variableMap)
|
||||
{
|
||||
///TODO
|
||||
_variableMap(variableMap) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -756,10 +703,9 @@ AggregateNode::AggregateNode (triagens::aql::Query* q,
|
|||
/// @brief toJson, for AggregateNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AggregateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void AggregateNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -779,9 +725,7 @@ void AggregateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -789,8 +733,8 @@ void AggregateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
ReturnNode::ReturnNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: _inVariable(q->registerVar(new Variable(base.get("inVariable")))) {
|
||||
///TODO
|
||||
: ExecutionNode(base),
|
||||
_inVariable(q->registerVar(new Variable(base.get("inVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -798,10 +742,9 @@ ReturnNode::ReturnNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson, for ReturnNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ReturnNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void ReturnNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -810,18 +753,19 @@ void ReturnNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
json("inVariable", _inVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ModificationNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ModificationNode::ModificationNode (triagens::aql::Query* q,
|
||||
basics::Json const& json)
|
||||
: ExecutionNode(),
|
||||
basics::Json const& base)
|
||||
: ExecutionNode(base),
|
||||
_vocbase(q->vocbase()),
|
||||
_collection(q->collections()->get(JsonHelper::getStringValue(json.json(), "collection", ""))),
|
||||
_options(json) {
|
||||
_collection(q->collections()->get(JsonHelper::getStringValue(base.json(), "collection", ""))),
|
||||
_options(base) {
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
TRI_ASSERT(_collection != nullptr);
|
||||
}
|
||||
|
@ -833,10 +777,7 @@ ModificationNode::ModificationNode (triagens::aql::Query* q,
|
|||
RemoveNode::RemoveNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: ModificationNode(q, base),
|
||||
_inVariable(q->registerVar(new Variable(base.get("inVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable"))))
|
||||
{
|
||||
|
||||
///TODO
|
||||
_outVariable(base.get("outVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -844,10 +785,9 @@ RemoveNode::RemoveNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RemoveNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void RemoveNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -864,9 +804,7 @@ void RemoveNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -876,8 +814,7 @@ void RemoveNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
InsertNode::InsertNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: ModificationNode(q, base),
|
||||
_inVariable(q->registerVar(new Variable(base.get("inVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
///TODO
|
||||
_outVariable(base.get("outVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -885,10 +822,9 @@ InsertNode::InsertNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InsertNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void InsertNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -905,9 +841,7 @@ void InsertNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -917,10 +851,8 @@ void InsertNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
UpdateNode::UpdateNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: ModificationNode(q, base),
|
||||
_inDocVariable(q->registerVar(new Variable(base.get("inDocVariable")))),
|
||||
_inKeyVariable(q->registerVar(new Variable(base.get("inKeyVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
|
||||
///TODO
|
||||
_inKeyVariable(base.get("inKeyVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("inKeyVariable")))),
|
||||
_outVariable(base.get("outVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -928,10 +860,9 @@ UpdateNode::UpdateNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UpdateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void UpdateNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -953,9 +884,7 @@ void UpdateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -965,9 +894,8 @@ void UpdateNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
ReplaceNode::ReplaceNode (triagens::aql::Query* q, basics::Json const& base)
|
||||
: ModificationNode(q, base),
|
||||
_inDocVariable(q->registerVar(new Variable(base.get("inDocVariable")))),
|
||||
_inKeyVariable(q->registerVar(new Variable(base.get("inKeyVariable")))),
|
||||
_outVariable(q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
///TODO
|
||||
_inKeyVariable(base.get("inKeyVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("inKeyVariable")))),
|
||||
_outVariable(base.get("outVariable").isEmpty() ? nullptr : q->registerVar(new Variable(base.get("outVariable")))) {
|
||||
fromJsonHelper(q, base);
|
||||
}
|
||||
|
||||
|
@ -975,10 +903,9 @@ ReplaceNode::ReplaceNode (triagens::aql::Query* q, basics::Json const& base)
|
|||
/// @brief toJson
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ReplaceNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
void ReplaceNode::toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone) {
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(indexTab, nodes, zone)); // call base class method
|
||||
Json json(ExecutionNode::toJsonHelperGeneric(nodes, zone)); // call base class method
|
||||
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
|
@ -1000,9 +927,7 @@ void ReplaceNode::toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
|||
}
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
nodes(json);
|
||||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace triagens {
|
|||
namespace aql {
|
||||
|
||||
class ExecutionBlock;
|
||||
class ExecutionPlan;
|
||||
class Ast;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -97,25 +98,28 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief factory from json.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static ExecutionNode* fromJsonFactory (Ast const* ast,
|
||||
basics::Json const& json);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief default constructor
|
||||
/// @brief constructor using an id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExecutionNode () : _estimatedCost(0), _varUsageValid(false) {
|
||||
ExecutionNode (size_t id)
|
||||
: _id(id),
|
||||
_estimatedCost(0),
|
||||
_varUsageValid(false) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor with one dependency
|
||||
/// @brief constructor using a JSON struct
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExecutionNode (ExecutionNode* ep) {
|
||||
_dependencies.push_back(ep);
|
||||
ExecutionNode (triagens::basics::Json const& json)
|
||||
: ExecutionNode(triagens::basics::JsonHelper::getNumericValue<size_t>(json.json(), "id", 0)) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor, free dependencies
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -129,6 +133,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the node's id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline size_t id () const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -144,6 +156,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks whether we know a type of this kind; throws exception if not.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void validateType (int type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -248,7 +261,6 @@ namespace triagens {
|
|||
basics::Json const& base);
|
||||
|
||||
triagens::basics::Json toJsonHelperGeneric (
|
||||
std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone);
|
||||
|
||||
|
@ -256,8 +268,7 @@ namespace triagens {
|
|||
/// @brief toJson
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -334,6 +345,12 @@ namespace triagens {
|
|||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief node id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t const _id;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief our dependent nodes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -388,7 +405,9 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SingletonNode () : ExecutionNode() {}
|
||||
SingletonNode (size_t id)
|
||||
: ExecutionNode(id) {
|
||||
}
|
||||
|
||||
SingletonNode (triagens::aql::Query* query, basics::Json const& base);
|
||||
|
||||
|
@ -404,8 +423,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -413,7 +431,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new SingletonNode();
|
||||
auto c = new SingletonNode(_id);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -445,13 +463,13 @@ namespace triagens {
|
|||
/// @brief constructor with a vocbase and a collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
EnumerateCollectionNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
public:
|
||||
|
||||
EnumerateCollectionNode (TRI_vocbase_t* vocbase,
|
||||
EnumerateCollectionNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
Variable const* outVariable)
|
||||
: ExecutionNode(),
|
||||
: ExecutionNode(id),
|
||||
_vocbase(vocbase),
|
||||
_collection(collection),
|
||||
_outVariable(outVariable){
|
||||
|
@ -460,6 +478,8 @@ namespace triagens {
|
|||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
EnumerateCollectionNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -472,8 +492,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -481,7 +500,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new EnumerateCollectionNode(_vocbase, _collection, _outVariable);
|
||||
auto c = new EnumerateCollectionNode(_id, _vocbase, _collection, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -532,7 +551,6 @@ namespace triagens {
|
|||
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class EnumerateListNode
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -552,16 +570,20 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
EnumerateListNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
EnumerateListNode (Variable const* inVariable,
|
||||
EnumerateListNode (size_t id,
|
||||
Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ExecutionNode(), _inVariable(inVariable), _outVariable(outVariable) {
|
||||
: ExecutionNode(id),
|
||||
_inVariable(inVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
EnumerateListNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -574,8 +596,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -583,7 +604,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new EnumerateListNode(_inVariable, _outVariable);
|
||||
auto c = new EnumerateListNode(_id, _inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -645,7 +666,7 @@ namespace triagens {
|
|||
/// @brief class IndexRangeNode
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class IndexRangeNode: public ExecutionNode {
|
||||
class IndexRangeNode : public ExecutionNode {
|
||||
|
||||
friend class ExecutionBlock;
|
||||
friend class IndexRangeBlock;
|
||||
|
@ -690,12 +711,13 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
IndexRangeNode (TRI_vocbase_t* vocbase,
|
||||
IndexRangeNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
Variable const* outVariable,
|
||||
Index* index,
|
||||
vector<RangeInfo>* ranges)
|
||||
: ExecutionNode(),
|
||||
: ExecutionNode(id),
|
||||
_vocbase(vocbase),
|
||||
_collection(collection),
|
||||
_outVariable(outVariable),
|
||||
|
@ -724,8 +746,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -733,7 +754,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new IndexRangeNode(_vocbase, _collection, _outVariable, _index,
|
||||
auto c = new IndexRangeNode(_id, _vocbase, _collection, _outVariable, _index,
|
||||
_ranges);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
|
@ -815,16 +836,23 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
LimitNode (size_t id,
|
||||
size_t offset,
|
||||
size_t limit)
|
||||
: ExecutionNode(id),
|
||||
_offset(offset),
|
||||
_limit(limit) {
|
||||
}
|
||||
|
||||
LimitNode (size_t id,
|
||||
size_t limit)
|
||||
: ExecutionNode(id),
|
||||
_offset(0),
|
||||
_limit(limit) {
|
||||
}
|
||||
|
||||
LimitNode (triagens::aql::Query* query, basics::Json const& base);
|
||||
|
||||
LimitNode (size_t o, size_t l)
|
||||
: ExecutionNode(), _offset(o), _limit(l) {
|
||||
}
|
||||
|
||||
LimitNode (size_t l)
|
||||
: ExecutionNode(), _offset(0), _limit(l) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -837,8 +865,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -846,7 +873,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new LimitNode(_offset, _limit);
|
||||
auto c = new LimitNode(_id, _offset, _limit);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -892,11 +919,10 @@ namespace triagens {
|
|||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CalculationNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
CalculationNode (Expression* expr,
|
||||
CalculationNode (size_t id,
|
||||
Expression* expr,
|
||||
Variable const* outVariable)
|
||||
: ExecutionNode(),
|
||||
: ExecutionNode(id),
|
||||
_expression(expr),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
|
@ -904,6 +930,8 @@ namespace triagens {
|
|||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
CalculationNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -926,8 +954,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -935,7 +962,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new CalculationNode(_expression->clone(), _outVariable);
|
||||
auto c = new CalculationNode(_id, _expression->clone(), _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1032,8 +1059,11 @@ namespace triagens {
|
|||
triagens::aql::Query* Q,
|
||||
basics::Json const& base);
|
||||
|
||||
SubqueryNode (ExecutionNode* subquery, Variable const* outVariable)
|
||||
: ExecutionNode(), _subquery(subquery), _outVariable(outVariable) {
|
||||
SubqueryNode (size_t id,
|
||||
ExecutionNode* subquery, Variable const* outVariable)
|
||||
: ExecutionNode(id),
|
||||
_subquery(subquery),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_subquery != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
|
@ -1051,8 +1081,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1060,7 +1089,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new SubqueryNode(_subquery->clone(), _outVariable);
|
||||
auto c = new SubqueryNode(_id, _subquery->clone(), _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1073,6 +1102,16 @@ namespace triagens {
|
|||
return _subquery;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setter for subquery
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setSubquery (ExecutionNode* subquery) {
|
||||
TRI_ASSERT(subquery != nullptr);
|
||||
TRI_ASSERT(_subquery == nullptr); // do not allow overwriting an existing subquery
|
||||
_subquery = subquery;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the cost of a subquery node is the cost of its unique dependency
|
||||
/// times a small constant
|
||||
|
@ -1138,14 +1177,16 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
FilterNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
FilterNode (Variable const* inVariable)
|
||||
: ExecutionNode(), _inVariable(inVariable) {
|
||||
FilterNode (size_t id,
|
||||
Variable const* inVariable)
|
||||
: ExecutionNode(id),
|
||||
_inVariable(inVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
}
|
||||
|
||||
FilterNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1158,8 +1199,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1167,7 +1207,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new FilterNode(_inVariable);
|
||||
auto c = new FilterNode(_id, _inVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1221,14 +1261,16 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SortNode (size_t id,
|
||||
std::vector<std::pair<Variable const*, bool>> elements)
|
||||
: ExecutionNode(id),
|
||||
_elements(elements) {
|
||||
}
|
||||
|
||||
SortNode (triagens::aql::Query* query,
|
||||
basics::Json const& base,
|
||||
std::vector<std::pair<Variable const*, bool>> elements);
|
||||
|
||||
SortNode (std::vector<std::pair<Variable const*, bool>> elements)
|
||||
: ExecutionNode(), _elements(elements) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1241,8 +1283,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1250,7 +1291,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new SortNode(_elements);
|
||||
auto c = new SortNode(_id, _elements);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1311,22 +1352,23 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
AggregateNode (triagens::aql::Query* query,
|
||||
basics::Json const& base,
|
||||
Variable const* outVariable,
|
||||
std::unordered_map<VariableId, std::string const> const& variableMap,
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables);
|
||||
|
||||
AggregateNode (std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables,
|
||||
AggregateNode (size_t id,
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables,
|
||||
Variable const* outVariable,
|
||||
std::unordered_map<VariableId, std::string const> const& variableMap)
|
||||
: ExecutionNode(),
|
||||
: ExecutionNode(id),
|
||||
_aggregateVariables(aggregateVariables),
|
||||
_outVariable(outVariable),
|
||||
_variableMap(variableMap) {
|
||||
// outVariable can be a nullptr
|
||||
}
|
||||
|
||||
AggregateNode (triagens::aql::Query* query,
|
||||
basics::Json const& base,
|
||||
Variable const* outVariable,
|
||||
std::unordered_map<VariableId, std::string const> const& variableMap,
|
||||
std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1339,8 +1381,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1348,7 +1389,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new AggregateNode(_aggregateVariables, _outVariable, _variableMap);
|
||||
auto c = new AggregateNode(_id, _aggregateVariables, _outVariable, _variableMap);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1435,14 +1476,16 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
ReturnNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
ReturnNode (Variable const* inVariable)
|
||||
: ExecutionNode(), _inVariable(inVariable) {
|
||||
ReturnNode (size_t id,
|
||||
Variable const* inVariable)
|
||||
: ExecutionNode(id),
|
||||
_inVariable(inVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
}
|
||||
|
||||
ReturnNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1455,8 +1498,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1464,7 +1506,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new ReturnNode(_inVariable);
|
||||
auto c = new ReturnNode(_id, _inVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1520,10 +1562,11 @@ namespace triagens {
|
|||
|
||||
protected:
|
||||
|
||||
ModificationNode (TRI_vocbase_t* vocbase,
|
||||
ModificationNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options)
|
||||
: ExecutionNode(),
|
||||
: ExecutionNode(id),
|
||||
_vocbase(vocbase),
|
||||
_collection(collection),
|
||||
_options(options) {
|
||||
|
@ -1581,14 +1624,13 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
RemoveNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
RemoveNode (TRI_vocbase_t* vocbase,
|
||||
RemoveNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
: ModificationNode(id, vocbase, collection, options),
|
||||
_inVariable(inVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
|
@ -1596,6 +1638,8 @@ namespace triagens {
|
|||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
RemoveNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1608,8 +1652,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1617,7 +1660,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new RemoveNode(_vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
auto c = new RemoveNode(_id, _vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1693,14 +1736,13 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
InsertNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
InsertNode (TRI_vocbase_t* vocbase,
|
||||
InsertNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
: ModificationNode(id, vocbase, collection, options),
|
||||
_inVariable(inVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
||||
|
@ -1708,6 +1750,8 @@ namespace triagens {
|
|||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
InsertNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1720,8 +1764,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1729,7 +1772,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new InsertNode(_vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
auto c = new InsertNode(_id, _vocbase, _collection, _options, _inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1804,15 +1847,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
UpdateNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
UpdateNode (TRI_vocbase_t* vocbase,
|
||||
UpdateNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inDocVariable,
|
||||
Variable const* inKeyVariable,
|
||||
Variable const* outVariable)
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
: ModificationNode(id, vocbase, collection, options),
|
||||
_inDocVariable(inDocVariable),
|
||||
_inKeyVariable(inKeyVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
@ -1822,6 +1864,8 @@ namespace triagens {
|
|||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
UpdateNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1834,8 +1878,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1843,7 +1886,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new UpdateNode(_vocbase, _collection, _options, _inDocVariable, _inKeyVariable, _outVariable);
|
||||
auto c = new UpdateNode(_id, _vocbase, _collection, _options, _inDocVariable, _inKeyVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
@ -1928,15 +1971,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
ReplaceNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
ReplaceNode (TRI_vocbase_t* vocbase,
|
||||
ReplaceNode (size_t id,
|
||||
TRI_vocbase_t* vocbase,
|
||||
Collection* collection,
|
||||
ModificationOptions const& options,
|
||||
Variable const* inDocVariable,
|
||||
Variable const* inKeyVariable,
|
||||
Variable const* outVariable)
|
||||
: ModificationNode(vocbase, collection, options),
|
||||
: ModificationNode(id, vocbase, collection, options),
|
||||
_inDocVariable(inDocVariable),
|
||||
_inKeyVariable(inKeyVariable),
|
||||
_outVariable(outVariable) {
|
||||
|
@ -1946,6 +1988,8 @@ namespace triagens {
|
|||
// _outVariable might be a nullptr
|
||||
}
|
||||
|
||||
ReplaceNode (triagens::aql::Query* Q, basics::Json const& base);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1958,8 +2002,7 @@ namespace triagens {
|
|||
/// @brief export to JSON
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void toJsonHelper (std::map<ExecutionNode*, int>& indexTab,
|
||||
triagens::basics::Json& nodes,
|
||||
virtual void toJsonHelper (triagens::basics::Json& nodes,
|
||||
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1967,7 +2010,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionNode* clone () const {
|
||||
auto c = new ReplaceNode(_vocbase, _collection, _options, _inDocVariable, _inKeyVariable, _outVariable);
|
||||
auto c = new ReplaceNode(_id, _vocbase, _collection, _options, _inDocVariable, _inKeyVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,13 @@
|
|||
#include "Aql/Query.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Aql/WalkerWorker.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "Utils/Exception.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
using namespace triagens::basics;
|
||||
using JsonHelper = triagens::basics::JsonHelper;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -49,7 +52,9 @@ using namespace triagens::basics;
|
|||
|
||||
ExecutionPlan::ExecutionPlan ()
|
||||
: _nodes(),
|
||||
_root(nullptr) {
|
||||
_ids(),
|
||||
_root(nullptr),
|
||||
_nextId(0) {
|
||||
|
||||
_nodes.reserve(8);
|
||||
}
|
||||
|
@ -84,23 +89,18 @@ ExecutionPlan* ExecutionPlan::instanciateFromAst (Ast const* ast) {
|
|||
try {
|
||||
plan->_root = plan->fromNode(ast, root);
|
||||
plan->findVarUsage();
|
||||
/*
|
||||
std::cout << "ESTIMATED COST = €" << plan->getCost() << "\n";
|
||||
|
||||
/*
|
||||
auto JsonPlan = plan->_root->toJson();
|
||||
auto JsonString = JsonPlan.toString();
|
||||
|
||||
std::cout << JsonString << "\n";
|
||||
|
||||
auto otherPlan = ExecutionPlan::instanciateFromJson (ast,
|
||||
JsonPlan);
|
||||
auto otherJsonString = otherPlan->_root->toJson().toString();
|
||||
std::cout << otherJsonString << "\n";
|
||||
/// TRI_ASSERT(otherJsonString == JsonString);
|
||||
/// JsonHelper
|
||||
return otherPlan;
|
||||
|
||||
/*/ return plan;
|
||||
*/
|
||||
return plan;
|
||||
}
|
||||
catch (...) {
|
||||
delete plan;
|
||||
|
@ -109,14 +109,11 @@ ExecutionPlan* ExecutionPlan::instanciateFromAst (Ast const* ast) {
|
|||
}
|
||||
|
||||
ExecutionPlan* ExecutionPlan::instanciateFromJson (Ast const* ast,
|
||||
triagens::basics::Json const& Json)
|
||||
{
|
||||
|
||||
triagens::basics::Json const& Json) {
|
||||
auto plan = new ExecutionPlan();
|
||||
|
||||
try {
|
||||
plan->_root = plan->fromJson(ast, Json);
|
||||
std::cout << "running findvarusage\n";
|
||||
plan->findVarUsage();
|
||||
return plan;
|
||||
}
|
||||
|
@ -126,6 +123,22 @@ ExecutionPlan* ExecutionPlan::instanciateFromJson (Ast const* ast,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a node by its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExecutionNode* ExecutionPlan::getNodeById (size_t id) const {
|
||||
auto it = _ids.find(id);
|
||||
|
||||
if (it != _ids.end()) {
|
||||
// node found
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
// node unknown
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "node not found");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -175,9 +188,12 @@ ModificationOptions ExecutionPlan::createOptions (AstNode const* node) {
|
|||
|
||||
ExecutionNode* ExecutionPlan::addNode (ExecutionNode* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->id() > 0);
|
||||
|
||||
try {
|
||||
_nodes.push_back(node);
|
||||
_ids.insert(std::make_pair(node->id(), node));
|
||||
|
||||
return node;
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -200,7 +216,7 @@ CalculationNode* ExecutionPlan::createTemporaryCalculation (Ast const* ast,
|
|||
auto expr = new Expression(ast->query()->executor(), const_cast<AstNode*>(expression));
|
||||
|
||||
try {
|
||||
auto en = new CalculationNode(expr, out);
|
||||
auto en = new CalculationNode(nextId(), expr, out);
|
||||
|
||||
addNode(reinterpret_cast<ExecutionNode*>(en));
|
||||
return en;
|
||||
|
@ -263,20 +279,20 @@ ExecutionNode* ExecutionPlan::fromNodeFor (Ast const* ast,
|
|||
if (collection == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "no collection for EnumerateCollection");
|
||||
}
|
||||
en = addNode(new EnumerateCollectionNode(ast->query()->vocbase(), collection, v));
|
||||
en = addNode(new EnumerateCollectionNode(nextId(), ast->query()->vocbase(), collection, v));
|
||||
}
|
||||
else if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// second operand is already a variable
|
||||
auto inVariable = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(inVariable != nullptr);
|
||||
en = addNode(new EnumerateListNode(inVariable, v));
|
||||
en = addNode(new EnumerateListNode(nextId(), inVariable, v));
|
||||
}
|
||||
else {
|
||||
// second operand is some misc. expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new EnumerateListNode(calc->outVariable(), v));
|
||||
en = addNode(new EnumerateListNode(nextId(), calc->outVariable(), v));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -303,14 +319,14 @@ ExecutionNode* ExecutionPlan::fromNodeFilter (Ast const* ast,
|
|||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new FilterNode(v));
|
||||
en = addNode(new FilterNode(nextId(), v));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new FilterNode(calc->outVariable()));
|
||||
en = addNode(new FilterNode(nextId(), calc->outVariable()));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -344,14 +360,14 @@ ExecutionNode* ExecutionPlan::fromNodeLet (Ast const* ast,
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
en = addNode(new SubqueryNode(subquery, v));
|
||||
en = addNode(new SubqueryNode(nextId(), subquery, v));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression, including references to other variables
|
||||
auto expr = new Expression(ast->query()->executor(), const_cast<AstNode*>(expression));
|
||||
|
||||
try {
|
||||
en = addNode(new CalculationNode(expr, v));
|
||||
en = addNode(new CalculationNode(nextId(), expr, v));
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
|
@ -419,7 +435,7 @@ ExecutionNode* ExecutionPlan::fromNodeSort (Ast const* ast,
|
|||
previous = (*it);
|
||||
}
|
||||
|
||||
auto en = addNode(new SortNode(elements));
|
||||
auto en = addNode(new SortNode(nextId(), elements));
|
||||
|
||||
return addDependency(previous, en);
|
||||
}
|
||||
|
@ -479,7 +495,7 @@ ExecutionNode* ExecutionPlan::fromNodeCollect (Ast const* ast,
|
|||
}
|
||||
|
||||
// inject a sort node for all expressions / variables that we just picked up...
|
||||
auto sort = addNode(new SortNode(sortElements));
|
||||
auto sort = addNode(new SortNode(nextId(), sortElements));
|
||||
sort->addDependency(previous);
|
||||
previous = sort;
|
||||
|
||||
|
@ -492,7 +508,7 @@ ExecutionNode* ExecutionPlan::fromNodeCollect (Ast const* ast,
|
|||
outVariable = static_cast<Variable*>(v->getData());
|
||||
}
|
||||
|
||||
auto en = addNode(new AggregateNode(aggregateVariables, outVariable, ast->variables()->variables(false)));
|
||||
auto en = addNode(new AggregateNode(nextId(), aggregateVariables, outVariable, ast->variables()->variables(false)));
|
||||
|
||||
return addDependency(previous, en);
|
||||
}
|
||||
|
@ -513,7 +529,7 @@ ExecutionNode* ExecutionPlan::fromNodeLimit (Ast const* ast,
|
|||
TRI_ASSERT(offset->type == NODE_TYPE_VALUE);
|
||||
TRI_ASSERT(count->type == NODE_TYPE_VALUE);
|
||||
|
||||
auto en = addNode(new LimitNode(static_cast<size_t>(offset->getIntValue()), static_cast<size_t>(count->getIntValue())));
|
||||
auto en = addNode(new LimitNode(nextId(), static_cast<size_t>(offset->getIntValue()), static_cast<size_t>(count->getIntValue())));
|
||||
|
||||
return addDependency(previous, en);
|
||||
}
|
||||
|
@ -536,13 +552,13 @@ ExecutionNode* ExecutionPlan::fromNodeReturn (Ast const* ast,
|
|||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new ReturnNode(v));
|
||||
en = addNode(new ReturnNode(nextId(), v));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new ReturnNode(calc->outVariable()));
|
||||
en = addNode(new ReturnNode(nextId(), calc->outVariable()));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -565,7 +581,7 @@ ExecutionNode* ExecutionPlan::fromNodeRemove (Ast const* ast,
|
|||
auto collection = collections->get(collectionName);
|
||||
|
||||
if (collection == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "no collection for RemoveNode");
|
||||
}
|
||||
|
||||
auto expression = node->getMember(2);
|
||||
|
@ -575,13 +591,13 @@ ExecutionNode* ExecutionPlan::fromNodeRemove (Ast const* ast,
|
|||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new RemoveNode(ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
en = addNode(new RemoveNode(nextId(), ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new RemoveNode(ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
en = addNode(new RemoveNode(nextId(), ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -609,13 +625,13 @@ ExecutionNode* ExecutionPlan::fromNodeInsert (Ast const* ast,
|
|||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new InsertNode(ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
en = addNode(new InsertNode(nextId(), ast->query()->vocbase(), collection, options, v, nullptr));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new InsertNode(ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
en = addNode(new InsertNode(nextId(), ast->query()->vocbase(), collection, options, calc->outVariable(), nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -661,13 +677,13 @@ ExecutionNode* ExecutionPlan::fromNodeUpdate (Ast const* ast,
|
|||
// document operand is already a variable
|
||||
auto v = static_cast<Variable*>(docExpression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), collection, options, v, keyVariable, nullptr));
|
||||
en = addNode(new UpdateNode(nextId(), ast->query()->vocbase(), collection, options, v, keyVariable, nullptr));
|
||||
}
|
||||
else {
|
||||
// document operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, docExpression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new UpdateNode(ast->query()->vocbase(), collection, options, calc->outVariable(), keyVariable, nullptr));
|
||||
en = addNode(new UpdateNode(nextId(), ast->query()->vocbase(), collection, options, calc->outVariable(), keyVariable, nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -713,13 +729,13 @@ ExecutionNode* ExecutionPlan::fromNodeReplace (Ast const* ast,
|
|||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(docExpression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), collection, options, v, keyVariable, nullptr));
|
||||
en = addNode(new ReplaceNode(nextId(), ast->query()->vocbase(), collection, options, v, keyVariable, nullptr));
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, docExpression);
|
||||
calc->addDependency(previous);
|
||||
en = addNode(new ReplaceNode(ast->query()->vocbase(), collection, options, calc->outVariable(), keyVariable, nullptr));
|
||||
en = addNode(new ReplaceNode(nextId(), ast->query()->vocbase(), collection, options, calc->outVariable(), keyVariable, nullptr));
|
||||
previous = calc;
|
||||
}
|
||||
|
||||
|
@ -734,7 +750,7 @@ ExecutionNode* ExecutionPlan::fromNode (Ast const* ast,
|
|||
AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
ExecutionNode* en = addNode(new SingletonNode());
|
||||
ExecutionNode* en = addNode(new SingletonNode(nextId()));
|
||||
|
||||
size_t const n = node->numMembers();
|
||||
|
||||
|
@ -973,49 +989,73 @@ void ExecutionPlan::removeNode (ExecutionNode* node) {
|
|||
return removeNodes(toRemove);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a plan from the JSON provided
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExecutionNode* ExecutionPlan::fromJson (Ast const* ast,
|
||||
Json const& json) {
|
||||
/// return = addNode(new SingletonNode());
|
||||
ExecutionNode* ret = nullptr;
|
||||
Json nodes = json.get("nodes");
|
||||
|
||||
ExecutionNode* oneNode;
|
||||
|
||||
if (!nodes.isList()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
uint size = nodes.size();
|
||||
|
||||
_nodes.reserve(size);
|
||||
|
||||
for (uint i = 0; i < size; i++) {
|
||||
Json oneJsonNode = nodes.at(i);
|
||||
if (!oneJsonNode.isArray()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
uint index = JsonHelper::getNumericValue<uint>(oneJsonNode.json(), "index", 0);
|
||||
ret = oneNode = ExecutionNode::fromJsonFactory(ast,
|
||||
oneJsonNode);
|
||||
_nodes[index] = oneNode; // TODO: get it from the "index"
|
||||
if (! nodes.isList()) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "nodes is not a list");
|
||||
}
|
||||
|
||||
for (uint i = 0; i < size; i++) {
|
||||
// first, re-create all nodes from the JSON, using the node ids
|
||||
// no dependency links will be set up in this step
|
||||
auto const size = nodes.size();
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
Json oneJsonNode = nodes.at(i);
|
||||
if (!oneJsonNode.isArray()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
|
||||
if (! oneJsonNode.isArray()) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "json node is not an array");
|
||||
}
|
||||
|
||||
ret = ExecutionNode::fromJsonFactory(ast,
|
||||
oneJsonNode);
|
||||
|
||||
addNode(ret);
|
||||
|
||||
TRI_ASSERT(ret != nullptr);
|
||||
|
||||
if (ret->getType() == triagens::aql::ExecutionNode::SUBQUERY) {
|
||||
// found a subquery node. now do magick here
|
||||
Json subquery = oneJsonNode.get("subquery");
|
||||
// create the subquery nodes from the "subquery" sub-node
|
||||
auto subqueryNode = fromJson(ast, subquery);
|
||||
|
||||
// register the just created subquery
|
||||
static_cast<SubqueryNode*>(ret)->setSubquery(subqueryNode);
|
||||
}
|
||||
}
|
||||
|
||||
// all nodes have been created. now add the dependencies
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
Json oneJsonNode = nodes.at(i);
|
||||
|
||||
if (! oneJsonNode.isArray()) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "json node is not an array");
|
||||
}
|
||||
|
||||
// read the node's own id
|
||||
auto thisId = JsonHelper::getNumericValue<size_t>(oneJsonNode.json(), "id", 0);
|
||||
auto thisNode = getNodeById(thisId);
|
||||
|
||||
// now re-link the dependencies
|
||||
Json dependencies = oneJsonNode.get("dependencies");
|
||||
if (JsonHelper::isList(dependencies.json())) {
|
||||
uint nDependencies = dependencies.size();
|
||||
for (uint j = 0; j < nDependencies; j ++) {
|
||||
if (JsonHelper::isNumber(dependencies.at(j).json())) {
|
||||
uint which = round(dependencies.at(j).json()->_value._number);
|
||||
/// todo: assert dependency index
|
||||
_nodes[i]->addDependency(_nodes[which]);
|
||||
size_t const nDependencies = dependencies.size();
|
||||
|
||||
}
|
||||
for (size_t j = 0; j < nDependencies; j ++) {
|
||||
if (JsonHelper::isNumber(dependencies.at(j).json())) {
|
||||
auto depId = JsonHelper::getNumericValue<size_t>(dependencies.at(j).json(), 0);
|
||||
thisNode->addDependency(getNodeById(depId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -84,6 +84,20 @@ namespace triagens {
|
|||
static ExecutionPlan* instanciateFromJson (Ast const* ast,
|
||||
triagens::basics::Json const& Json);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the next value for a node id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline size_t nextId () {
|
||||
return ++_nextId;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a node by its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExecutionNode* getNodeById (size_t id) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the root node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -281,6 +295,12 @@ namespace triagens {
|
|||
|
||||
std::vector<ExecutionNode*> _nodes;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief map from node id to the actual node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<size_t, ExecutionNode*> _ids;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief root node of the plan
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -293,6 +313,12 @@ namespace triagens {
|
|||
|
||||
std::unordered_map<VariableId, ExecutionNode*> _varSetBy;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief auto-increment sequence for node ids
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t _nextId;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ AqlValue Expression::execute (AQL_TRANSACTION_V8* trx,
|
|||
}
|
||||
}
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid simple expression");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -157,7 +157,7 @@ void Expression::analyzeExpression () {
|
|||
_data = _node->toJsonValue(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
if (_data == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid json in simple expression");
|
||||
}
|
||||
|
||||
_type = JSON;
|
||||
|
@ -200,7 +200,20 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
auto j = result.extractArrayMember(trx, myCollection, name);
|
||||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, j.steal()));
|
||||
}
|
||||
/*
|
||||
else if (node->type == NODE_TYPE_INDEXED_ACCESS) {
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
auto member = node->getMember(0);
|
||||
auto index = node->getMember(1);
|
||||
|
||||
TRI_document_collection_t const* myCollection = nullptr;
|
||||
AqlValue result = executeSimpleExpression(member, &myCollection, trx, docColls, argv, startPos, vars, regs);
|
||||
|
||||
auto j = result.extractListMember(trx, myCollection, name);
|
||||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, j.steal()));
|
||||
}
|
||||
*/
|
||||
else if (node->type == NODE_TYPE_LIST) {
|
||||
auto list = new Json(Json::List);
|
||||
|
||||
|
@ -261,7 +274,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
// fall-through to exception
|
||||
}
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled type in simple expression");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -44,13 +44,13 @@ Optimizer::Optimizer () {
|
|||
// remove filters from the query that are not necessary at all
|
||||
// rule should be executed relatively early because it enables removal
|
||||
// of then-unused filter variables
|
||||
registerRule(removeUnnecessaryFiltersRule, 10000);
|
||||
//registerRule(removeUnnecessaryFiltersRule, 10000);
|
||||
|
||||
// move calculations up the dependency chain (to pull them out of inner loops etc.)
|
||||
// TODO: validate if this is really an optimization
|
||||
// registerRule(moveCalculationsUpRule, 1000);
|
||||
|
||||
registerRule(removeUnnecessaryCalculationsRule, 999);
|
||||
//registerRule(removeUnnecessaryCalculationsRule, 999);
|
||||
|
||||
// Now sort them by pass:
|
||||
std::stable_sort(_rules.begin(), _rules.end());
|
||||
|
|
|
@ -75,7 +75,7 @@ int triagens::aql::removeUnnecessaryFiltersRule (Optimizer* opt,
|
|||
}
|
||||
else {
|
||||
// filter is always false
|
||||
/*
|
||||
/* TODO
|
||||
// get all dependent nodes of the filter node
|
||||
std::vector<ExecutionNode*> stack;
|
||||
stack.push_back(n);
|
||||
|
@ -114,7 +114,7 @@ int triagens::aql::removeUnnecessaryFiltersRule (Optimizer* opt,
|
|||
}
|
||||
|
||||
if (removeNode) {
|
||||
std::cout << "INSERTING NODE OF TYPE: " << current->getTypeString() << "\n";
|
||||
std::cout << "REMOVING NODE " << current << " OF TYPE: " << current->getTypeString() << "\n";
|
||||
toRemove.insert(current);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -381,7 +381,7 @@ v8::Handle<v8::Value> V8Executor::compileExpression () {
|
|||
v8::String::New("--script--"));
|
||||
|
||||
if (compiled.IsEmpty()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to compile v8 expression");
|
||||
}
|
||||
|
||||
return compiled->Run();
|
||||
|
@ -475,7 +475,7 @@ void V8Executor::generateCodeUnaryOperator (AstNode const* node) {
|
|||
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||
}
|
||||
|
||||
_buffer->appendText("aql.");
|
||||
|
@ -498,7 +498,7 @@ void V8Executor::generateCodeBinaryOperator (AstNode const* node) {
|
|||
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||
}
|
||||
|
||||
bool wrap = (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
||||
|
@ -536,7 +536,7 @@ void V8Executor::generateCodeTernaryOperator (AstNode const* node) {
|
|||
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||
}
|
||||
|
||||
_buffer->appendText("aql.");
|
||||
|
@ -859,12 +859,10 @@ void V8Executor::generateCodeNode (AstNode const* node) {
|
|||
case NODE_TYPE_VARIABLE:
|
||||
case NODE_TYPE_PARAMETER:
|
||||
// we're not expecting these types here
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type in code generator");
|
||||
|
||||
default:
|
||||
// TODO: remove debug output
|
||||
std::cout << "NODE TYPE NOT IMPLEMENTED (" << node->getTypeString() << ")\n";
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "node type not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,19 @@ namespace triagens {
|
|||
const char*,
|
||||
const std::string&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a numeric value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> static T getNumericValue (TRI_json_t const* json,
|
||||
T defaultValue) {
|
||||
if (isNumber(json)) {
|
||||
return (T) json->_value._number;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a numeric sub-element, or a default it is does not exist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue