mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
b7a2add68c
|
@ -64,7 +64,7 @@ AstNode::~AstNode () {
|
|||
/// the caller is responsible for freeing the JSON later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* AstNode::toJson (TRI_memory_zone_t* zone) {
|
||||
TRI_json_t* AstNode::toJson (TRI_memory_zone_t* zone) const {
|
||||
TRI_json_t* node = TRI_CreateArrayJson(zone);
|
||||
|
||||
if (node == nullptr) {
|
||||
|
@ -151,7 +151,7 @@ TRI_json_t* AstNode::toJson (TRI_memory_zone_t* zone) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AstNode::toJson (TRI_json_t* json,
|
||||
TRI_memory_zone_t* zone) {
|
||||
TRI_memory_zone_t* zone) const {
|
||||
TRI_ASSERT(TRI_IsListJson(json));
|
||||
|
||||
TRI_json_t* node = toJson(zone);
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace triagens {
|
|||
/// the caller is responsible for freeing the JSON later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_json_s* toJson (TRI_memory_zone_t*);
|
||||
struct TRI_json_s* toJson (TRI_memory_zone_t*) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a JSON representation of the node to the JSON list specified
|
||||
|
@ -173,7 +173,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void toJson (TRI_json_t*,
|
||||
TRI_memory_zone_t*);
|
||||
TRI_memory_zone_t*) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not a value node is of numeric type
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Utils/Exception.h"
|
||||
|
||||
using namespace triagens::basics;
|
||||
using namespace triagens::arango;
|
||||
|
@ -82,8 +83,7 @@ ExecutionBlock* ExecutionBlock::instanciatePlan (ExecutionPlan const* ep) {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
TRI_ASSERT(false);
|
||||
break;
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
vector<ExecutionPlan*> deps = ep->getDependencies();
|
||||
|
@ -117,26 +117,26 @@ int ExecutionBlock::staticAnalysisRecursion (
|
|||
_depth++;
|
||||
curVar = 0;
|
||||
auto p = static_cast<EnumerateCollectionPlan const*>(_exePlan);
|
||||
varTab.insert(make_pair(p->_outVarNumber, VarDefPlace(_depth, 0)));
|
||||
varTab.insert(make_pair(p->_outVariable->id, VarDefPlace(_depth, 0)));
|
||||
break;
|
||||
}
|
||||
case ExecutionPlan::ENUMERATE_LIST: {
|
||||
_depth++;
|
||||
curVar = 0;
|
||||
auto p = static_cast<EnumerateListPlan const*>(_exePlan);
|
||||
varTab.insert(make_pair(p->_outVarNumber, VarDefPlace(_depth, 0)));
|
||||
varTab.insert(make_pair(p->_outVariable->id, VarDefPlace(_depth, 0)));
|
||||
break;
|
||||
}
|
||||
case ExecutionPlan::CALCULATION: {
|
||||
curVar++;
|
||||
auto p = static_cast<CalculationPlan const*>(_exePlan);
|
||||
varTab.insert(make_pair(p->_varNumber, VarDefPlace(_depth, curVar)));
|
||||
varTab.insert(make_pair(p->_outVariable->id, VarDefPlace(_depth, curVar)));
|
||||
break;
|
||||
}
|
||||
case ExecutionPlan::PROJECTION: {
|
||||
curVar++;
|
||||
auto p = static_cast<ProjectionPlan const*>(_exePlan);
|
||||
varTab.insert(make_pair(p->_outVar, VarDefPlace(_depth, curVar)));
|
||||
varTab.insert(make_pair(p->_outVariable->id, VarDefPlace(_depth, curVar)));
|
||||
break;
|
||||
}
|
||||
// TODO: potentially more cases
|
||||
|
|
|
@ -177,15 +177,9 @@ void EnumerateCollectionPlan::toJsonHelper (std::map<ExecutionPlan*, int>& index
|
|||
}
|
||||
|
||||
// Now put info about vocbase and cid in there
|
||||
if (_vocbase == nullptr) {
|
||||
json("vocbase", Json("<nullptr>"));
|
||||
}
|
||||
else {
|
||||
json("vocbase", Json(_vocbase->_name));
|
||||
}
|
||||
json("collection", Json(_collname))
|
||||
("outVarNumber", Json(static_cast<double>(_outVarNumber)))
|
||||
("outVarName", Json(_outVarName));
|
||||
json("database", Json(_vocbase->_name))
|
||||
("collection", Json(_collname))
|
||||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -208,11 +202,8 @@ void EnumerateListPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
json("varNumber", Json(static_cast<double>(_varNumber)))
|
||||
("varName", Json(_varName))
|
||||
("outVarNumber", Json(static_cast<double>(_outVarNumber)))
|
||||
("outVarName", Json(_outVarName));
|
||||
|
||||
json("inVariable", _inVariable->toJson())
|
||||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -260,9 +251,9 @@ void CalculationPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
json("varNumber", Json(static_cast<double>(_varNumber)))
|
||||
("varName", Json(_varName))
|
||||
("expression", _expression->toJson(TRI_UNKNOWN_MEM_ZONE));
|
||||
|
||||
json("expression", _expression->toJson(TRI_UNKNOWN_MEM_ZONE))
|
||||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -285,9 +276,8 @@ void SubqueryPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
json("varNumber", Json(static_cast<double>(_varNumber)))
|
||||
("varName", Json(_varName))
|
||||
("subquery", _subquery->toJson(TRI_UNKNOWN_MEM_ZONE));
|
||||
json("subquery", _subquery->toJson(TRI_UNKNOWN_MEM_ZONE))
|
||||
("outVariable", _outVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -314,10 +304,9 @@ void ProjectionPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
for (auto it = _keepAttributes.begin(); it != _keepAttributes.end(); ++it) {
|
||||
vec(Json(*it));
|
||||
}
|
||||
json("inVarNumber", Json(static_cast<double>(_inVar)))
|
||||
("inVarName", Json(_inVarName))
|
||||
("outVarNumber", Json(static_cast<double>(_outVar)))
|
||||
("outVarName", Json(_outVarName))
|
||||
|
||||
json("inVariable", _inVariable->toJson())
|
||||
("outVariable", _outVariable->toJson())
|
||||
("keepAttributes", vec);
|
||||
|
||||
// And add it:
|
||||
|
@ -341,9 +330,8 @@ void FilterPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// Now put info about offset and limit in
|
||||
json("varName", Json(_varName))
|
||||
("varNumber", Json(static_cast<double>(_varNumber)));
|
||||
|
||||
json("inVariable", _inVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -366,21 +354,14 @@ void SortPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Json numbers(Json::List, _varNumbers.size());
|
||||
for (auto it = _varNumbers.begin(); it != _varNumbers.end(); ++it) {
|
||||
numbers(Json(static_cast<double>(*it)));
|
||||
Json values(Json::List, _elements.size());
|
||||
for (auto it = _elements.begin(); it != _elements.end(); ++it) {
|
||||
Json element(Json::Array);
|
||||
element("inVariable", (*it).first->toJson())
|
||||
("ascending", Json((*it).second));
|
||||
values(element);
|
||||
}
|
||||
Json names(Json::List, _varNames.size());
|
||||
for (auto it = _varNames.begin(); it != _varNames.end(); ++it) {
|
||||
names(Json(*it));
|
||||
}
|
||||
Json vec(Json::List, _sortAscending.size());
|
||||
for (auto it = _sortAscending.begin(); it != _sortAscending.end(); ++it) {
|
||||
vec(Json(*it));
|
||||
}
|
||||
json("varNumbers", numbers)
|
||||
("varNames", names)
|
||||
("sortAscending", vec);
|
||||
json("elements", values);
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -403,18 +384,20 @@ void AggregateOnUnsortedPlan::toJsonHelper (std::map<ExecutionPlan*, int>& index
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Json numbers(Json::List, _varNumbers.size());
|
||||
for (auto it = _varNumbers.begin(); it != _varNumbers.end(); ++it) {
|
||||
numbers(Json(static_cast<double>(*it)));
|
||||
|
||||
Json values(Json::List, _aggregateVariables.size());
|
||||
for (auto it = _aggregateVariables.begin(); it != _aggregateVariables.end(); ++it) {
|
||||
Json variable(Json::Array);
|
||||
variable("outVariable", (*it).first->toJson())
|
||||
("inVariable", (*it).second->toJson());
|
||||
values(variable);
|
||||
}
|
||||
Json names(Json::List, _varNames.size());
|
||||
for (auto it = _varNames.begin(); it != _varNames.end(); ++it) {
|
||||
names(Json(*it));
|
||||
json("aggregates", values);
|
||||
|
||||
// output variable might be empty
|
||||
if (_outVariable != nullptr) {
|
||||
json("outVariable", _outVariable->toJson());
|
||||
}
|
||||
json("varNumbers", numbers)
|
||||
("varNames", names)
|
||||
("outVarNumber", Json(static_cast<double>(_outVarNumber)))
|
||||
("outVarName", Json(_outVarName));
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -437,8 +420,8 @@ void RootPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
json("varNumber", Json(static_cast<double>(_varNumber)))
|
||||
("varName" , Json(_varName));
|
||||
|
||||
json("inVariable", _inVariable->toJson());
|
||||
|
||||
// And add it:
|
||||
int len = static_cast<int>(nodes.size());
|
||||
|
@ -446,246 +429,6 @@ void RootPlan::toJsonHelper (std::map<ExecutionPlan*, int>& indexTab,
|
|||
indexTab.insert(make_pair(this, len));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace triagens::basics;
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MyWorker2 : public triagens::aql::ExecutionPlan::WalkerWorker {
|
||||
public:
|
||||
int count;
|
||||
MyWorker2 () : count(0) {};
|
||||
~MyWorker2 () {};
|
||||
void before (triagens::aql::ExecutionPlan* ep) {
|
||||
std::cout << "Before node of type " << ep->getTypeString()
|
||||
<< std::endl;
|
||||
count++;
|
||||
}
|
||||
void after (triagens::aql::ExecutionPlan* ep) {
|
||||
std::cout << "After node of type " << ep->getTypeString()
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void testExecutionPlans () {
|
||||
Json a(12);
|
||||
Json b(Json::Array);
|
||||
b("a",a);
|
||||
std::cout << b.toString() << std::endl;
|
||||
std::cout << a.toString() << std::endl;
|
||||
std::cout << "Got here" << std::endl;
|
||||
|
||||
auto ec = new EnumerateCollectionPlan(nullptr, "guck", 1, "X");
|
||||
Json jjj(ec->toJson());
|
||||
cout << jjj.toString() << endl;
|
||||
auto li = new LimitPlan(12, 17);
|
||||
li->addDependency(ec);
|
||||
jjj = li->toJson();
|
||||
cout << jjj.toString() << endl;
|
||||
|
||||
TRI_json_t* json = Json(12);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(true);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(Json::Null);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(Json::String);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(Json::List);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(Json::Array);
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
json = Json(Json::Array, 10)
|
||||
("myinteger", Json(12))
|
||||
("mystring", Json("hallo"))
|
||||
("mybool", Json(false))
|
||||
("mynull", Json(Json::Null))
|
||||
("mylist", Json(Json::List, 3)
|
||||
(Json(1))
|
||||
(Json(2))
|
||||
(Json(3)))
|
||||
("myarray", Json(Json::Array, 2)
|
||||
("a",Json("hallo"))
|
||||
("b",Json(13)));
|
||||
cout << JsonHelper::toString(json) << endl;
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
Json j(Json::Array);
|
||||
j("a", Json(12))
|
||||
("b", Json(true))
|
||||
("c", Json(Json::List)
|
||||
(Json(1))(Json(2))(Json(3)))
|
||||
("d", Json(Json::Array)
|
||||
("x", Json(12))
|
||||
("y", Json(true)));
|
||||
cout << j.toString() << endl;
|
||||
|
||||
// We expect to see exactly two copies here:
|
||||
Json jjjj = j.copy(); // create an explicit copy
|
||||
Json jj(12);
|
||||
|
||||
cout << "Before assignment" << jj.toString() << endl;
|
||||
jj = j; // this steals the pointer from j
|
||||
|
||||
cout << jjjj.toString();
|
||||
cout << jj.toString();
|
||||
|
||||
Json k = jj.get("c");
|
||||
Json l = k.at(2);
|
||||
|
||||
cout << l.toString() << endl;
|
||||
|
||||
cout << "and now a complete test" << endl << endl;
|
||||
|
||||
// Here we want to build the unoptimised plan for:
|
||||
//
|
||||
// LET A = [1,2,3]
|
||||
// FOR g IN guck
|
||||
// FILTER g.name == "Wurst"
|
||||
// SORT g.vorname
|
||||
// LIMIT 2, 10
|
||||
// FOR i IN A
|
||||
// LET X = { "vorname": g.vorname, "addresse": g.addresse,
|
||||
// "nr": i*2 }
|
||||
// RETURN X
|
||||
//
|
||||
//
|
||||
{
|
||||
AstNode* a;
|
||||
AstNode* b;
|
||||
AstNode* c;
|
||||
ExecutionPlan* e;
|
||||
ExecutionPlan* n;
|
||||
|
||||
// Singleton
|
||||
e = new SingletonPlan();
|
||||
|
||||
// LET A = [1,2,3]
|
||||
a = new AstNode(NODE_TYPE_LIST);
|
||||
b = new AstNode(NODE_TYPE_VALUE);
|
||||
b->setValueType(VALUE_TYPE_INT);
|
||||
b->setIntValue(1);
|
||||
a->addMember(b);
|
||||
b = new AstNode(NODE_TYPE_VALUE);
|
||||
b->setValueType(VALUE_TYPE_INT);
|
||||
b->setIntValue(2);
|
||||
a->addMember(b);
|
||||
b = new AstNode(NODE_TYPE_VALUE);
|
||||
b->setValueType(VALUE_TYPE_INT);
|
||||
b->setIntValue(3);
|
||||
a->addMember(b);
|
||||
n = new CalculationPlan(new AqlExpression(a), 1, "A");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// FOR g IN guck
|
||||
n = new EnumerateCollectionPlan(nullptr, "guck", 2, "g");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// FILTER g.name == "Wurst"
|
||||
a = new AstNode(NODE_TYPE_OPERATOR_BINARY_EQ);
|
||||
b = new AstNode(NODE_TYPE_VALUE);
|
||||
b->setValueType(VALUE_TYPE_STRING);
|
||||
b->setStringValue("g.name");
|
||||
a->addMember(b);
|
||||
b = new AstNode(NODE_TYPE_VALUE);
|
||||
b->setValueType(VALUE_TYPE_STRING);
|
||||
b->setStringValue("Wurst");
|
||||
a->addMember(b);
|
||||
n = new CalculationPlan(new AqlExpression(a), 2, "_1");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
n = new FilterPlan(2, "_1");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// SORT g.vorname
|
||||
a = new AstNode(NODE_TYPE_VALUE);
|
||||
a->setValueType(VALUE_TYPE_STRING);
|
||||
a->setStringValue("g.vorname");
|
||||
n = new CalculationPlan(new AqlExpression(a), 3, "_2");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
std::vector<VariableId> vars;
|
||||
std::vector<std::string> names;
|
||||
std::vector<bool> asc;
|
||||
vars.push_back(3);
|
||||
names.push_back(string("_2"));
|
||||
asc.push_back(true);
|
||||
n = new SortPlan(vars, names, asc);
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// LIMIT 2, 10
|
||||
n = new LimitPlan(2, 10);
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// FOR i in A
|
||||
n = new EnumerateListPlan(1, "A", 2, "i");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// LET X = {"vorname": g.vorname, "addresse": g.addresse, "nr": i*2}
|
||||
a = new AstNode(NODE_TYPE_ARRAY);
|
||||
b = new AstNode(NODE_TYPE_ARRAY_ELEMENT);
|
||||
b->setValueType(VALUE_TYPE_STRING);
|
||||
b->setStringValue("vorname");
|
||||
c = new AstNode(NODE_TYPE_VALUE);
|
||||
c->setValueType(VALUE_TYPE_STRING);
|
||||
c->setStringValue("g.vorname");
|
||||
b->addMember(c);
|
||||
a->addMember(b);
|
||||
b = new AstNode(NODE_TYPE_ARRAY_ELEMENT);
|
||||
b->setValueType(VALUE_TYPE_STRING);
|
||||
b->setStringValue("adresse");
|
||||
c = new AstNode(NODE_TYPE_VALUE);
|
||||
c->setValueType(VALUE_TYPE_STRING);
|
||||
c->setStringValue("g.addresse");
|
||||
b->addMember(c);
|
||||
a->addMember(b);
|
||||
b = new AstNode(NODE_TYPE_ARRAY_ELEMENT);
|
||||
b->setValueType(VALUE_TYPE_STRING);
|
||||
b->setStringValue("nr");
|
||||
c = new AstNode(NODE_TYPE_VALUE);
|
||||
c->setValueType(VALUE_TYPE_STRING);
|
||||
c->setStringValue("i*2");
|
||||
b->addMember(c);
|
||||
a->addMember(b);
|
||||
n = new CalculationPlan(new AqlExpression(a), 4, "X");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
// RETURN X
|
||||
n = new RootPlan(4, "X");
|
||||
n->addDependency(e);
|
||||
e = n;
|
||||
|
||||
cout << e->toJson().toString() << endl;
|
||||
MyWorker2 w;
|
||||
e->walk(w);
|
||||
cout << "Count is: " << w.count << endl;
|
||||
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <VocBase/voc-types.h>
|
||||
#include <VocBase/vocbase.h>
|
||||
|
||||
#include "Aql/Expression.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Aql/Types.h"
|
||||
|
||||
|
@ -336,10 +337,12 @@ namespace triagens {
|
|||
|
||||
EnumerateCollectionPlan (TRI_vocbase_t* vocbase,
|
||||
std::string collname,
|
||||
VariableId outVarNumber,
|
||||
std::string outVarName)
|
||||
Variable const* outVariable)
|
||||
: ExecutionPlan(), _vocbase(vocbase), _collname(collname),
|
||||
_outVarNumber(outVarNumber), _outVarName(outVarName) {
|
||||
_outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -371,8 +374,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new EnumerateCollectionPlan(_vocbase, _collname,
|
||||
_outVarNumber, _outVarName);
|
||||
auto c = new EnumerateCollectionPlan(_vocbase, _collname, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -396,16 +398,10 @@ namespace triagens {
|
|||
std::string _collname;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarNumber, output variable
|
||||
/// @brief output variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _outVarNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _outVarName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -428,10 +424,12 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
EnumerateListPlan (VariableId varNumber, std::string varName,
|
||||
VariableId outVarNumber, std::string outVarName)
|
||||
: ExecutionPlan(), _varNumber(varNumber), _varName(varName),
|
||||
_outVarNumber(outVarNumber), _outVarName(outVarName) {
|
||||
EnumerateListPlan (Variable const* inVariable,
|
||||
Variable const* outVariable)
|
||||
: ExecutionPlan(), _inVariable(inVariable), _outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -463,8 +461,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new EnumerateListPlan(_varNumber, _varName,
|
||||
_outVarNumber, _outVarName);
|
||||
auto c = new EnumerateListPlan(_inVariable, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -476,28 +473,16 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumber, input variable
|
||||
/// @brief input variable to read from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _varNumber;
|
||||
Variable const* _inVariable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varName, name of variable to read from
|
||||
/// @brief output variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _varName;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarNumber, output variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _outVarNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _outVarName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -593,14 +578,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
ProjectionPlan (VariableId inVar,
|
||||
std::string inVarName,
|
||||
VariableId outVar,
|
||||
std::string outVarName,
|
||||
ProjectionPlan (Variable const* inVariable,
|
||||
Variable const* outVariable,
|
||||
std::vector<std::string> keepAttributes)
|
||||
: ExecutionPlan(), _inVar(inVar), _inVarName(inVarName),
|
||||
_outVar(outVar), _outVarName(outVarName),
|
||||
: ExecutionPlan(), _inVariable(inVariable), _outVariable(outVariable),
|
||||
_keepAttributes(keepAttributes) {
|
||||
|
||||
TRI_ASSERT(inVariable != nullptr);
|
||||
TRI_ASSERT(outVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -632,8 +617,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new ProjectionPlan(_inVar, _inVarName, _outVar, _outVarName,
|
||||
_keepAttributes);
|
||||
auto c = new ProjectionPlan(_inVariable, _outVariable, _keepAttributes);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -645,28 +629,16 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief input variable
|
||||
/// @brief input variable to read from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _inVar;
|
||||
Variable const* _inVariable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _inVarName, name of variable to read from
|
||||
/// @brief output variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _inVarName;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief output variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _outVar;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _outVarName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief vector of attributes to leave in the object
|
||||
|
@ -695,10 +667,11 @@ namespace triagens {
|
|||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CalculationPlan (AqlExpression* expr, VariableId varNumber,
|
||||
std::string varName)
|
||||
: ExecutionPlan(), _expression(expr), _varNumber(varNumber),
|
||||
_varName(varName) {
|
||||
CalculationPlan (Expression* expr, Variable const* outVariable)
|
||||
: ExecutionPlan(), _expression(expr), _outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_expression != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -740,11 +713,19 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new CalculationPlan(_expression->clone(), _varNumber, _varName);
|
||||
auto c = new CalculationPlan(_expression->clone(), _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return out variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable const* outVariable () const {
|
||||
return _outVariable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief private data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -755,19 +736,13 @@ namespace triagens {
|
|||
/// @brief we need to have an expression and where to write the result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlExpression* _expression;
|
||||
Expression* _expression;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumber, global number of variable to write to
|
||||
/// @brief output variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _varNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _varName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -790,10 +765,11 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SubqueryPlan (ExecutionPlan* subquery, VariableId varNumber,
|
||||
std::string varName)
|
||||
: ExecutionPlan(), _subquery(subquery), _varNumber(varNumber),
|
||||
_varName(varName) {
|
||||
SubqueryPlan (ExecutionPlan* subquery, Variable const* outVariable)
|
||||
: ExecutionPlan(), _subquery(subquery), _outVariable(outVariable) {
|
||||
|
||||
TRI_ASSERT(_subquery != nullptr);
|
||||
TRI_ASSERT(_outVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -825,7 +801,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new SubqueryPlan(_subquery->clone(), _varNumber, _varName);
|
||||
auto c = new SubqueryPlan(_subquery->clone(), _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -851,16 +827,10 @@ namespace triagens {
|
|||
ExecutionPlan* _subquery;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumber, global number of variable to write to
|
||||
/// @brief variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _varNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _varName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -883,8 +853,10 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
FilterPlan (VariableId varNumber, std::string varName)
|
||||
: ExecutionPlan(), _varNumber(varNumber), _varName(varName) {
|
||||
FilterPlan (Variable const* inVariable)
|
||||
: ExecutionPlan(), _inVariable(inVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -916,7 +888,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new FilterPlan(_varNumber, _varName);
|
||||
auto c = new FilterPlan(_inVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -928,16 +900,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumber, input variable
|
||||
/// @brief input variable to read from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _varNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varName, name of variable to read from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _varName;
|
||||
Variable const* _inVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -960,11 +926,8 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SortPlan (std::vector<VariableId> varNumbers,
|
||||
std::vector<std::string> varNames,
|
||||
std::vector<bool> sortAscending)
|
||||
: ExecutionPlan(), _varNumbers(varNumbers), _varNames(varNames),
|
||||
_sortAscending(sortAscending) {
|
||||
SortPlan (std::vector<std::pair<Variable const*, bool>> elements)
|
||||
: ExecutionPlan(), _elements(elements) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -996,7 +959,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new SortPlan(_varNumbers, _varNames, _sortAscending);
|
||||
auto c = new SortPlan(_elements);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -1008,22 +971,11 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumbers, input variables for sorting
|
||||
/// @brief pairs, consisting of variable and sort direction
|
||||
/// (true = ascending | false = descending)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<VariableId> _varNumbers;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNames, name of variables for sorting
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::string> _varNames;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief vector of attributes to sort by
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<bool> _sortAscending;
|
||||
std::vector<std::pair<Variable const*, bool>> _elements;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1047,12 +999,9 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
AggregateOnUnsortedPlan (std::vector<VariableId> varNumbers,
|
||||
std::vector<std::string> varNames,
|
||||
VariableId outVarNumber,
|
||||
std::string outVarName)
|
||||
: ExecutionPlan(), _varNumbers(varNumbers), _varNames(varNames),
|
||||
_outVarNumber(outVarNumber), _outVarName(outVarName) {
|
||||
AggregateOnUnsortedPlan (std::vector<std::pair<Variable const*, Variable const*>> aggregateVariables,
|
||||
Variable const* outVariable)
|
||||
: ExecutionPlan(), _aggregateVariables(aggregateVariables), _outVariable(outVariable) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1084,8 +1033,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new AggregateOnUnsortedPlan(_varNumbers, _varNames,
|
||||
_outVarNumber, _outVarName);
|
||||
auto c = new AggregateOnUnsortedPlan(_aggregateVariables, _outVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -1097,28 +1045,16 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNumbers, input variables for the aggregation
|
||||
/// @brief input/output variables for the aggregation (out = in)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<VariableId> _varNumbers;
|
||||
std::vector<std::pair<Variable const*, Variable const*>> _aggregateVariables;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _varNames, name of variables for the aggregation
|
||||
/// @brief output variable to write to (might be null)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::string> _varNames;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief output variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _outVarNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _outVarName, name of variable to write to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _outVarName;
|
||||
Variable const* _outVariable;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1142,8 +1078,10 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
RootPlan (VariableId varNumber, std::string varName)
|
||||
: ExecutionPlan(), _varNumber(varNumber), _varName(varName) {
|
||||
RootPlan (Variable const* inVariable)
|
||||
: ExecutionPlan(), _inVariable(inVariable) {
|
||||
|
||||
TRI_ASSERT(_inVariable != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1175,7 +1113,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ExecutionPlan* clone () const {
|
||||
auto c = new RootPlan(_varNumber, _varName);
|
||||
auto c = new RootPlan(_inVariable);
|
||||
cloneDependencies(c);
|
||||
return static_cast<ExecutionPlan*>(c);
|
||||
}
|
||||
|
@ -1186,9 +1124,7 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
VariableId _varNumber;
|
||||
|
||||
std::string _varName;
|
||||
Variable const* _inVariable;
|
||||
|
||||
};
|
||||
} // namespace triagens::aql
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, expression
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/Expression.h"
|
||||
#include "Aql/Types.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Utils/Exception.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Expression::Expression (V8Executor* executor,
|
||||
AstNode const* node)
|
||||
: _executor(executor),
|
||||
_node(node) {
|
||||
|
||||
TRI_ASSERT(_executor != nullptr);
|
||||
TRI_ASSERT(_node != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Expression::~Expression () {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute the expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue* Expression::execute (AqlItem* item) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -0,0 +1,133 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AQL, expression
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Max Neunhoeffer
|
||||
/// @author Copyright 2014, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_AQL_EXPRESSION_H
|
||||
#define ARANGODB_AQL_EXPRESSION_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace aql {
|
||||
|
||||
struct AqlItem;
|
||||
struct AqlValue;
|
||||
class V8Executor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AqlExpression, used in execution plans and execution blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Expression {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor, using an AST start node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Expression (V8Executor*,
|
||||
AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~Expression ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the underlying AST node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline AstNode const* node () {
|
||||
return _node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clone the expression, needed to clone execution plans
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Expression* clone () {
|
||||
// We do not need to copy the _ast, since it is managed by the
|
||||
// query object and the memory management of the ASTs
|
||||
return new Expression(_executor, _node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a Json representation of the expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::basics::Json toJson (TRI_memory_zone_t* zone) const {
|
||||
return triagens::basics::Json(zone, _node->toJson(zone));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute the expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue* execute (AqlItem*);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the V8 executor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8Executor* _executor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the AST node that contains the expression to execute
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// do we need a (possibly empty) subquery entry here?
|
||||
AstNode const* _node;
|
||||
|
||||
};
|
||||
|
||||
} // namespace triagens::aql
|
||||
} // namespace triagens
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "Aql/Parser.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/QueryResult.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
|
||||
|
@ -107,7 +108,7 @@ bool Parser::configureWriteQuery (QueryType type,
|
|||
/// @brief parse the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult Parser::parse () {
|
||||
QueryResult Parser::parse () {
|
||||
// start main scope
|
||||
auto scopes = _ast->scopes();
|
||||
scopes->start(AQL_SCOPE_MAIN);
|
||||
|
@ -134,7 +135,7 @@ ParseResult Parser::parse () {
|
|||
|
||||
TRI_ASSERT(scopes->numActive() == 0);
|
||||
|
||||
ParseResult result;
|
||||
QueryResult result;
|
||||
result.collectionNames = _ast->collectionNames();
|
||||
result.bindParameters = _ast->bindParameters();
|
||||
result.json = _ast->toJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace triagens {
|
|||
|
||||
struct AstNode;
|
||||
class Query;
|
||||
struct QueryResult;
|
||||
class Parser;
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +205,7 @@ namespace triagens {
|
|||
/// @brief parse the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult parse ();
|
||||
QueryResult parse ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a parse error, position is specified as line / column
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "Aql/Ast.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/Expression.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Utils/Exception.h"
|
||||
|
@ -79,6 +80,30 @@ ExecutionPlan* PlanGenerator::fromAst (Ast const* ast) {
|
|||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a calculation node for an arbitrary expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CalculationPlan* PlanGenerator::createTemporaryCalculation (Ast const* ast,
|
||||
AstNode const* expression) {
|
||||
// generate a temporary variable
|
||||
auto out = ast->variables()->createTemporaryVariable();
|
||||
TRI_ASSERT(out != nullptr);
|
||||
|
||||
// generate a temporary calculation node
|
||||
auto expr = new Expression(ast->query()->executor(), const_cast<AstNode*>(expression));
|
||||
|
||||
try {
|
||||
return new CalculationPlan(expr, out);
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
delete expr;
|
||||
throw;
|
||||
// no need to delete "out" as this is automatically freed by the variables management
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds "previous" as dependency to "plan", returns "plan"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -123,29 +148,20 @@ ExecutionPlan* PlanGenerator::fromNodeFor (Ast const* ast,
|
|||
if (expression->type == NODE_TYPE_COLLECTION) {
|
||||
// second operand is a collection
|
||||
char const* collectionName = expression->getStringValue();
|
||||
plan = new EnumerateCollectionPlan(ast->query()->vocbase(), std::string(collectionName), v->id, v->name);
|
||||
plan = new EnumerateCollectionPlan(ast->query()->vocbase(), std::string(collectionName), v);
|
||||
}
|
||||
else if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// second operand is already a variable
|
||||
auto inVariable = static_cast<Variable*>(variable->getData());
|
||||
TRI_ASSERT(inVariable != nullptr);
|
||||
plan = new EnumerateListPlan(inVariable, v);
|
||||
}
|
||||
else {
|
||||
// generate a temporary variable
|
||||
auto out = ast->variables()->createTemporaryVariable();
|
||||
|
||||
// generate a temporary calculation node
|
||||
CalculationPlan* calc;
|
||||
auto expr = new AqlExpression(expression);
|
||||
// second operand is some misc. expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
|
||||
try {
|
||||
calc = new CalculationPlan(expr, out->id, out->name);
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
delete expr;
|
||||
throw;
|
||||
}
|
||||
|
||||
TRI_ASSERT(calc != nullptr);
|
||||
|
||||
try {
|
||||
plan = new EnumerateListPlan(out->id, out->name, v->id, v->name);
|
||||
plan = new EnumerateListPlan(calc->outVariable(), v);
|
||||
plan->addDependency(calc);
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -169,10 +185,30 @@ ExecutionPlan* PlanGenerator::fromNodeFilter (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_FILTER);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
auto variable = node->getMember(0);
|
||||
auto v = static_cast<Variable*>(variable->getData());
|
||||
auto expression = node->getMember(0);
|
||||
|
||||
ExecutionPlan* plan = nullptr;
|
||||
|
||||
if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
plan = new FilterPlan(v);
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
|
||||
try {
|
||||
plan = new FilterPlan(calc->outVariable());
|
||||
plan->addDependency(calc);
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
delete calc;
|
||||
}
|
||||
}
|
||||
|
||||
auto plan = new FilterPlan(v->id, v->name);
|
||||
return addDependency(previous, plan);
|
||||
}
|
||||
|
||||
|
@ -191,11 +227,18 @@ ExecutionPlan* PlanGenerator::fromNodeLet (Ast const* ast,
|
|||
|
||||
auto v = static_cast<Variable*>(variable->getData());
|
||||
|
||||
ExecutionPlan* plan = nullptr;
|
||||
|
||||
if (expression->type == NODE_TYPE_SUBQUERY) {
|
||||
// TODO: node might be a subquery. this is currently NOT handled
|
||||
auto expr = new AqlExpression(const_cast<AstNode*>(expression));
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression, including references to other variables
|
||||
auto expr = new Expression(ast->query()->executor(), const_cast<AstNode*>(expression));
|
||||
|
||||
try {
|
||||
auto plan = new CalculationPlan(expr, v->id, v->name);
|
||||
return addDependency(previous, plan);
|
||||
plan = new CalculationPlan(expr, v);
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
|
@ -204,6 +247,9 @@ ExecutionPlan* PlanGenerator::fromNodeLet (Ast const* ast,
|
|||
}
|
||||
}
|
||||
|
||||
return addDependency(previous, plan);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an execution plan element from an AST SORT node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -214,10 +260,55 @@ ExecutionPlan* PlanGenerator::fromNodeSort (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_SORT);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
auto list = node->getMember(0);
|
||||
TRI_ASSERT(list->type == NODE_TYPE_LIST);
|
||||
|
||||
return nullptr;
|
||||
std::vector<std::pair<Variable const*, bool>> elements;
|
||||
std::vector<CalculationPlan*> temp;
|
||||
|
||||
try {
|
||||
size_t const n = list->numMembers();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto element = list->getMember(i);
|
||||
TRI_ASSERT(element != nullptr);
|
||||
TRI_ASSERT(element->type == NODE_TYPE_SORT_ELEMENT);
|
||||
TRI_ASSERT(element->numMembers() == 1);
|
||||
|
||||
auto expression = element->getMember(0);
|
||||
|
||||
if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// sort operand is a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
elements.push_back(std::make_pair(v, element->getBoolValue()));
|
||||
}
|
||||
else {
|
||||
// sort operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
temp.push_back(calc);
|
||||
elements.push_back(std::make_pair(calc->outVariable(), element->getBoolValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
for (auto it = temp.begin(); it != temp.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
TRI_ASSERT(! elements.empty());
|
||||
|
||||
// properly link the temporary calculations in the plan
|
||||
for (auto it = temp.begin(); it != temp.end(); ++it) {
|
||||
(*it)->addDependency(previous);
|
||||
previous = (*it);
|
||||
}
|
||||
|
||||
auto plan = new SortPlan(elements);
|
||||
|
||||
return addDependency(previous, plan);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -269,11 +360,29 @@ ExecutionPlan* PlanGenerator::fromNodeReturn (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_RETURN);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
auto variable = node->getMember(0);
|
||||
// TODO: the operand type of return is not necessarily a variable...
|
||||
auto v = static_cast<Variable*>(variable->getData());
|
||||
auto expression = node->getMember(0);
|
||||
|
||||
auto plan = new RootPlan(v->id, v->name);
|
||||
ExecutionPlan* plan = nullptr;
|
||||
|
||||
if (expression->type == NODE_TYPE_REFERENCE) {
|
||||
// operand is already a variable
|
||||
auto v = static_cast<Variable*>(expression->getData());
|
||||
TRI_ASSERT(v != nullptr);
|
||||
plan = new RootPlan(v);
|
||||
}
|
||||
else {
|
||||
// operand is some misc expression
|
||||
auto calc = createTemporaryCalculation(ast, expression);
|
||||
|
||||
try {
|
||||
plan = new RootPlan(calc->outVariable());
|
||||
plan->addDependency(calc);
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
delete calc;
|
||||
}
|
||||
}
|
||||
|
||||
return addDependency(previous, plan);
|
||||
}
|
||||
|
@ -288,6 +397,8 @@ ExecutionPlan* PlanGenerator::fromNodeRemove (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REMOVE);
|
||||
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -301,6 +412,8 @@ ExecutionPlan* PlanGenerator::fromNodeInsert (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_INSERT);
|
||||
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -314,6 +427,8 @@ ExecutionPlan* PlanGenerator::fromNodeUpdate (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_UPDATE);
|
||||
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -327,6 +442,8 @@ ExecutionPlan* PlanGenerator::fromNodeReplace (Ast const* ast,
|
|||
TRI_ASSERT(node != nullptr && node->type == NODE_TYPE_REPLACE);
|
||||
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -340,6 +457,7 @@ ExecutionPlan* PlanGenerator::fromNode (Ast const* ast,
|
|||
|
||||
ExecutionPlan* plan = new SingletonPlan();
|
||||
|
||||
try {
|
||||
size_t const n = node->numMembers();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -419,6 +537,14 @@ ExecutionPlan* PlanGenerator::fromNode (Ast const* ast,
|
|||
|
||||
return plan;
|
||||
}
|
||||
catch (...) {
|
||||
// prevent memleak
|
||||
if (plan != nullptr) {
|
||||
delete plan;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace triagens {
|
|||
|
||||
class Ast;
|
||||
struct AstNode;
|
||||
class CalculationPlan;
|
||||
class ExecutionPlan;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -81,6 +82,13 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a calculation node for an arbitrary expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CalculationPlan* createTemporaryCalculation (Ast const*,
|
||||
AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds "previous" as dependency to "plan", returns "plan"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Aql/Parser.h"
|
||||
#include "Aql/PlanGenerator.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "BasicsC/json.h"
|
||||
#include "BasicsC/tri-strings.h"
|
||||
|
@ -163,23 +165,63 @@ void Query::registerError (int code,
|
|||
/// @brief execute an AQL query - TODO: implement and determine return type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult Query::execute () {
|
||||
QueryResult Query::execute () {
|
||||
try {
|
||||
Parser parser(this);
|
||||
parser.parse();
|
||||
parser.ast()->injectBindParameters(_bindParameters);
|
||||
parser.ast()->optimize();
|
||||
|
||||
ParseResult result(TRI_ERROR_NO_ERROR);
|
||||
result.json = parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
PlanGenerator generator;
|
||||
auto plan = generator.fromAst(parser.ast());
|
||||
|
||||
try {
|
||||
auto exec = ExecutionBlock::instanciatePlan(plan);
|
||||
|
||||
try {
|
||||
exec->staticAnalysis();
|
||||
|
||||
exec->initialize();
|
||||
exec->execute();
|
||||
|
||||
shared_ptr<AqlItem> value;
|
||||
while (nullptr != (value = exec->getOne())) {
|
||||
std::cout << value->getValue(0, 0)->toString() << std::endl;
|
||||
value.reset();
|
||||
}
|
||||
|
||||
exec->shutdown();
|
||||
delete exec;
|
||||
}
|
||||
catch (...) {
|
||||
delete exec;
|
||||
delete plan;
|
||||
// TODO: convert exception code
|
||||
return QueryResult(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
}
|
||||
catch (triagens::arango::Exception const& ex) {
|
||||
delete plan;
|
||||
return QueryResult(ex.code(), ex.message());
|
||||
}
|
||||
catch (...) {
|
||||
delete plan;
|
||||
// TODO: convert exception code
|
||||
return QueryResult(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
delete plan;
|
||||
|
||||
QueryResult result(TRI_ERROR_NO_ERROR);
|
||||
// result.json = parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (triagens::arango::Exception const& ex) {
|
||||
return ParseResult(ex.code(), ex.message());
|
||||
return QueryResult(ex.code(), ex.message());
|
||||
}
|
||||
catch (...) {
|
||||
return ParseResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
|
||||
return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,16 +229,16 @@ ParseResult Query::execute () {
|
|||
/// @brief parse an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult Query::parse () {
|
||||
QueryResult Query::parse () {
|
||||
try {
|
||||
Parser parser(this);
|
||||
return parser.parse();
|
||||
}
|
||||
catch (triagens::arango::Exception const& ex) {
|
||||
return ParseResult(ex.code(), ex.message());
|
||||
return QueryResult(ex.code(), ex.message());
|
||||
}
|
||||
catch (...) {
|
||||
return ParseResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
|
||||
return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/BindParameters.h"
|
||||
#include "Aql/ParseResult.h"
|
||||
#include "Aql/QueryResult.h"
|
||||
|
||||
struct TRI_json_s;
|
||||
struct TRI_vocbase_s;
|
||||
|
@ -95,6 +95,14 @@ namespace triagens {
|
|||
return _vocbase;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the V8 executor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline V8Executor* executor () {
|
||||
return _executor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the query type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -142,16 +150,16 @@ namespace triagens {
|
|||
char const* = nullptr);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute an AQL query - TODO: implement and determine return type
|
||||
/// @brief execute an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult execute ();
|
||||
QueryResult execute ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parse an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseResult parse ();
|
||||
QueryResult parse ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief explain an AQL query - TODO: implement and determine return type
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, parse results
|
||||
/// @brief Aql, query results
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
|
@ -27,8 +27,8 @@
|
|||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_AQL_PARSE_RESULT_H
|
||||
#define ARANGODB_AQL_PARSE_RESULT_H 1
|
||||
#ifndef ARANGODB_AQL_QUERY_RESULT_H
|
||||
#define ARANGODB_AQL_QUERY_RESULT_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "BasicsC/json.h"
|
||||
|
@ -37,13 +37,13 @@ namespace triagens {
|
|||
namespace aql {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct ParseResult
|
||||
// --SECTION-- struct QueryResult
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct ParseResult {
|
||||
ParseResult& operator= (ParseResult const& other) = delete;
|
||||
struct QueryResult {
|
||||
QueryResult& operator= (QueryResult const& other) = delete;
|
||||
|
||||
ParseResult (ParseResult&& other) {
|
||||
QueryResult (QueryResult&& other) {
|
||||
code = other.code;
|
||||
details = other.details;
|
||||
json = other.json;
|
||||
|
@ -51,7 +51,7 @@ namespace triagens {
|
|||
other.json = nullptr;
|
||||
}
|
||||
|
||||
ParseResult (int code,
|
||||
QueryResult (int code,
|
||||
std::string const& details)
|
||||
: code(code),
|
||||
details(details),
|
||||
|
@ -59,21 +59,21 @@ namespace triagens {
|
|||
json(nullptr) {
|
||||
}
|
||||
|
||||
explicit ParseResult (int code)
|
||||
explicit QueryResult (int code)
|
||||
: code(code),
|
||||
details(""),
|
||||
zone(TRI_UNKNOWN_MEM_ZONE),
|
||||
json(nullptr) {
|
||||
}
|
||||
|
||||
ParseResult ()
|
||||
QueryResult ()
|
||||
: code(TRI_ERROR_NO_ERROR),
|
||||
details(),
|
||||
zone(TRI_UNKNOWN_MEM_ZONE),
|
||||
json(nullptr) {
|
||||
}
|
||||
|
||||
~ParseResult () {
|
||||
~QueryResult () {
|
||||
if (json != nullptr) {
|
||||
TRI_FreeJson(zone, json);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, AST variable
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/Variable.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
using Json = triagens::basics::Json;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable::Variable (std::string const& name,
|
||||
VariableId id)
|
||||
: name(name),
|
||||
value(nullptr),
|
||||
id(id),
|
||||
refCount(0) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable::~Variable () {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a JSON representation of the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Json Variable::toJson () const {
|
||||
Json json(triagens::basics::Json::Array, 2);
|
||||
json("id", Json(static_cast<double>(id)))
|
||||
("name", Json(name));
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -1,5 +1,5 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, AST variables
|
||||
/// @brief Aql, AST variable
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
|
@ -31,6 +31,7 @@
|
|||
#define ARANGODB_AQL_VARIABLE_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace aql {
|
||||
|
@ -42,18 +43,23 @@ namespace triagens {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct Variable {
|
||||
Variable (std::string const& name,
|
||||
VariableId id,
|
||||
bool isUserDefined)
|
||||
: name(name),
|
||||
value(nullptr),
|
||||
id(id),
|
||||
refCount(0),
|
||||
isUserDefined(isUserDefined) {
|
||||
}
|
||||
|
||||
~Variable () {
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable (std::string const&,
|
||||
VariableId);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~Variable ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief registers a constant value for the variable
|
||||
|
@ -97,15 +103,49 @@ namespace triagens {
|
|||
--refCount;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the variable is user-defined
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isUserDefined () const {
|
||||
char const c = name[0];
|
||||
// variables starting with a number are user-defined
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a JSON representation of the variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::basics::Json toJson () const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief variable name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const name;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constant variable value (points to another AstNode)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* value;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief variable id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId const id;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief number of times the variable is used in the AST
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint32_t refCount;
|
||||
bool const isUserDefined;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -65,7 +65,11 @@ VariableGenerator::~VariableGenerator () {
|
|||
|
||||
Variable* VariableGenerator::createVariable (char const* name,
|
||||
bool isUserDefined) {
|
||||
auto variable = new Variable(std::string(name), nextId(), isUserDefined);
|
||||
auto variable = new Variable(std::string(name), nextId());
|
||||
|
||||
if (isUserDefined) {
|
||||
TRI_ASSERT(variable->isUserDefined());
|
||||
}
|
||||
|
||||
try {
|
||||
_variables.insert(std::make_pair(variable->id, variable));
|
||||
|
@ -85,7 +89,11 @@ Variable* VariableGenerator::createVariable (char const* name,
|
|||
|
||||
Variable* VariableGenerator::createVariable (std::string const& name,
|
||||
bool isUserDefined) {
|
||||
auto variable = new Variable(name, nextId(), isUserDefined);
|
||||
auto variable = new Variable(name, nextId());
|
||||
|
||||
if (isUserDefined) {
|
||||
TRI_ASSERT(variable->isUserDefined());
|
||||
}
|
||||
|
||||
try {
|
||||
_variables.insert(std::make_pair(variable->id, variable));
|
||||
|
@ -126,6 +134,8 @@ Variable* VariableGenerator::getVariable (VariableId id) const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string VariableGenerator::nextName () const {
|
||||
// note: if the naming scheme is adjusted, it may be necessary to adjust
|
||||
// Variable::isUserDefined, too!
|
||||
return std::to_string(_id); // to_string: c++11
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ add_executable(
|
|||
Aql/BindParameters.cpp
|
||||
Aql/ExecutionBlock.cpp
|
||||
Aql/ExecutionPlan.cpp
|
||||
Aql/Expression.cpp
|
||||
Aql/grammar.cpp
|
||||
Aql/Parser.cpp
|
||||
Aql/PlanGenerator.cpp
|
||||
|
@ -70,6 +71,7 @@ add_executable(
|
|||
Aql/Types.cpp
|
||||
Aql/tokens.cpp
|
||||
Aql/V8Executor.cpp
|
||||
Aql/Variable.cpp
|
||||
Aql/VariableGenerator.cpp
|
||||
BitIndexes/bitarray.cpp
|
||||
BitIndexes/bitarrayIndex.cpp
|
||||
|
|
|
@ -1515,9 +1515,12 @@ static v8::Handle<v8::Value> JS_AsyncRequest (v8::Arguments const& argv) {
|
|||
// - coordTransactionID (number)
|
||||
// - timeout (number)
|
||||
|
||||
if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
}
|
||||
// Disabled to allow communication originating in a DBserver:
|
||||
// 31.7.2014 Max
|
||||
|
||||
// if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
// TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
//}
|
||||
|
||||
ClusterComm* cc = ClusterComm::instance();
|
||||
|
||||
|
@ -1572,9 +1575,12 @@ static v8::Handle<v8::Value> JS_SyncRequest (v8::Arguments const& argv) {
|
|||
// - coordTransactionID (number)
|
||||
// - timeout (number)
|
||||
|
||||
if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
}
|
||||
// Disabled to allow communication originating in a DBserver:
|
||||
// 31.7.2014 Max
|
||||
|
||||
//if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
// TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
//}
|
||||
|
||||
ClusterComm* cc = ClusterComm::instance();
|
||||
|
||||
|
@ -1626,9 +1632,12 @@ static v8::Handle<v8::Value> JS_Enquire (v8::Arguments const& argv) {
|
|||
TRI_V8_EXCEPTION_USAGE(scope, "enquire(operationID)");
|
||||
}
|
||||
|
||||
if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
}
|
||||
// Disabled to allow communication originating in a DBserver:
|
||||
// 31.7.2014 Max
|
||||
|
||||
// if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
// TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
// }
|
||||
|
||||
ClusterComm* cc = ClusterComm::instance();
|
||||
|
||||
|
@ -1668,9 +1677,12 @@ static v8::Handle<v8::Value> JS_Wait (v8::Arguments const& argv) {
|
|||
// - shardID (string)
|
||||
// - timeout (number)
|
||||
|
||||
if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
}
|
||||
// Disabled to allow communication originating in a DBserver:
|
||||
// 31.7.2014 Max
|
||||
|
||||
// if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
// TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
// }
|
||||
|
||||
ClusterComm* cc = ClusterComm::instance();
|
||||
|
||||
|
@ -1742,9 +1754,12 @@ static v8::Handle<v8::Value> JS_Drop (v8::Arguments const& argv) {
|
|||
// - operationID (number)
|
||||
// - shardID (string)
|
||||
|
||||
if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
}
|
||||
// Disabled to allow communication originating in a DBserver:
|
||||
// 31.7.2014 Max
|
||||
|
||||
// if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
|
||||
// TRI_V8_EXCEPTION_INTERNAL(scope,"request works only in coordinator role");
|
||||
// }
|
||||
|
||||
ClusterComm* cc = ClusterComm::instance();
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ arangod_libarangod_a_SOURCES = \
|
|||
arangod/Aql/BindParameters.cpp \
|
||||
arangod/Aql/ExecutionBlock.cpp \
|
||||
arangod/Aql/ExecutionPlan.cpp \
|
||||
arangod/Aql/Expression.cpp \
|
||||
arangod/Aql/grammar.cpp \
|
||||
arangod/Aql/Parser.cpp \
|
||||
arangod/Aql/PlanGenerator.cpp \
|
||||
|
@ -51,6 +52,7 @@ arangod_libarangod_a_SOURCES = \
|
|||
arangod/Aql/Types.cpp \
|
||||
arangod/Aql/tokens.cpp \
|
||||
arangod/Aql/V8Executor.cpp \
|
||||
arangod/Aql/Variable.cpp \
|
||||
arangod/Aql/VariableGenerator.cpp \
|
||||
arangod/BitIndexes/bitarray.cpp \
|
||||
arangod/BitIndexes/bitarrayIndex.cpp \
|
||||
|
|
|
@ -5397,71 +5397,6 @@ static v8::Handle<v8::Value> JS_ParseAql (v8::Arguments const& argv) {
|
|||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief peng an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class MyWorker : public triagens::aql::ExecutionBlock::WalkerWorker {
|
||||
public:
|
||||
int count;
|
||||
MyWorker () : count(0) {};
|
||||
~MyWorker () {};
|
||||
void before (triagens::aql::ExecutionBlock* eb) {
|
||||
std::cout << "Before node of type " << eb->getPlan()->getTypeString()
|
||||
<< std::endl;
|
||||
count++;
|
||||
}
|
||||
void after (triagens::aql::ExecutionBlock* eb) {
|
||||
std::cout << "After node of type " << eb->getPlan()->getTypeString()
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
static v8::Handle<v8::Value> JS_PengAql (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
TRI_vocbase_t* vocbase = GetContextVocBase();
|
||||
|
||||
if (vocbase == nullptr) {
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "AQL_PENG()");
|
||||
}
|
||||
|
||||
triagens::aql::ExecutionPlan* singlePlan = new triagens::aql::SingletonPlan();
|
||||
triagens::aql::ExecutionPlan* enumPlan = new triagens::aql::EnumerateCollectionPlan(vocbase, "fuxx", 1, "f");
|
||||
enumPlan->addDependency(singlePlan);
|
||||
triagens::aql::ExecutionPlan* rootPlan = new triagens::aql::RootPlan(1,"X");
|
||||
rootPlan->addDependency(enumPlan);
|
||||
|
||||
triagens::aql::ExecutionBlock* exec = triagens::aql::ExecutionBlock::instanciatePlan (rootPlan);
|
||||
|
||||
exec->staticAnalysis();
|
||||
|
||||
MyWorker w;
|
||||
exec->walk(w);
|
||||
std::cout << "Count is " << w.count << std::endl;
|
||||
|
||||
exec->initialize();
|
||||
exec->execute();
|
||||
|
||||
shared_ptr<triagens::aql::AqlItem> value;
|
||||
while (nullptr != (value = exec->getOne())) {
|
||||
std::cout << "Peng" << std::endl;
|
||||
std::cout << value->getValue(0,0)->toString() << std::endl;
|
||||
value.reset();
|
||||
}
|
||||
|
||||
exec->shutdown();
|
||||
|
||||
delete exec;
|
||||
delete rootPlan;
|
||||
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5499,14 +5434,16 @@ static v8::Handle<v8::Value> JS_ExecuteAql (v8::Arguments const& argv) {
|
|||
// bind parameters will be freed by the query later
|
||||
triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), parameters);
|
||||
|
||||
auto parseResult = query.execute();
|
||||
auto queryResult = query.execute();
|
||||
|
||||
if (parseResult.code != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_FULL(scope, parseResult.code, parseResult.details);
|
||||
if (queryResult.code != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_FULL(scope, queryResult.code, queryResult.details);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(TRI_V8_STRING("ast"), TRI_ObjectJson(parseResult.json));
|
||||
if (queryResult.json != nullptr) {
|
||||
result->Set(TRI_V8_STRING("json"), TRI_ObjectJson(queryResult.json));
|
||||
}
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
@ -10778,7 +10715,6 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
|
|||
// new AQL functions. not intended to be used directly by end users
|
||||
TRI_AddGlobalFunctionVocbase(context, "AQL_EXECUTE", JS_ExecuteAql, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "AQL_PARSE", JS_ParseAql, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "AQL_PENG", JS_PengAql, true);
|
||||
|
||||
// cursor functions. not intended to be used by end users
|
||||
TRI_AddGlobalFunctionVocbase(context, "CURSOR", JS_Cursor, true);
|
||||
|
|
Loading…
Reference in New Issue