1
0
Fork 0

fixed creation of subqueries from JSON input

This commit is contained in:
Jan Steemann 2014-08-19 18:51:11 +02:00
parent f179c35f02
commit 99ce138c12
11 changed files with 523 additions and 460 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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");
}
// -----------------------------------------------------------------------------

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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
////////////////////////////////////////////////////////////////////////////////