1
0
Fork 0

Merge branch 'aql2' of https://github.com/triAGENS/ArangoDB into aql2

This commit is contained in:
Jan Steemann 2014-07-29 14:49:25 +02:00
commit 8eb7f5bd8a
6 changed files with 321 additions and 83 deletions

View File

@ -48,6 +48,10 @@ int ExecutionBlock::bind (std::map<std::string, struct TRI_json_s*>* params) {
ExecutionBlock* ExecutionBlock::instanciatePlan (ExecutionPlan const* ep) {
ExecutionBlock* eb;
switch (ep->getType()) {
case ExecutionPlan::SINGLETON: {
eb = new SingletonBlock(static_cast<SingletonPlan const*>(ep));
break;
}
case ExecutionPlan::ENUMERATE_COLLECTION: {
eb = new EnumerateCollectionBlock(static_cast<EnumerateCollectionPlan const*>(ep));
break;

View File

@ -35,6 +35,8 @@
#include "Aql/ExecutionPlan.h"
#include "Utils/transactions.h"
using namespace triagens::basics;
struct TRI_json_s;
namespace triagens {
@ -43,7 +45,7 @@ namespace triagens {
class ExecutionBlock {
public:
ExecutionBlock (ExecutionPlan const* ep)
: _exePlan(ep) { }
: _exePlan(ep), _done(false) { }
virtual ~ExecutionBlock ();
@ -99,6 +101,7 @@ namespace triagens {
for (auto it = _dependencies.begin(); it != _dependencies.end(); ++it) {
(*it)->initialize();
}
// FIXME: report errors from above
return TRI_ERROR_NO_ERROR;
}
@ -110,6 +113,8 @@ namespace triagens {
for (auto it = _dependencies.begin(); it != _dependencies.end(); ++it) {
(*it)->execute();
}
// FIXME: report errors from above
_done = false;
return TRI_ERROR_NO_ERROR;
}
@ -117,12 +122,13 @@ namespace triagens {
for (auto it = _dependencies.begin(); it != _dependencies.end(); ++it) {
(*it)->shutdown();
}
// FIXME: report errors from above
return TRI_ERROR_NO_ERROR;
}
virtual AqlValue* getOne () = 0;
virtual AqlItem* getOne () = 0;
std::vector<AqlValue*> getSome (int atLeast, int atMost);
std::vector<AqlItem*> getSome (int atLeast, int atMost);
bool skip (int number);
@ -133,7 +139,8 @@ namespace triagens {
protected:
ExecutionPlan const* _exePlan;
std::vector<ExecutionBlock*> _dependencies;
std::deque<AqlValue*> _buffer;
std::deque<AqlItem*> _buffer;
bool _done;
public:
@ -142,12 +149,49 @@ namespace triagens {
};
class SingletonBlock : public ExecutionBlock {
public:
SingletonBlock (SingletonPlan const* ep)
: ExecutionBlock(ep) {
}
~SingletonBlock () {
}
int initialize () {
ExecutionBlock::initialize();
return TRI_ERROR_NO_ERROR;
}
int execute () {
ExecutionBlock::execute();
return TRI_ERROR_NO_ERROR;
}
int shutdown () {
return TRI_ERROR_NO_ERROR;
}
AqlItem* getOne () {
if (_done) {
return nullptr;
}
auto p = reinterpret_cast<SingletonPlan const*>(_exePlan);
AqlItem* res = new AqlItem(p->_nrVars);
return res;
}
};
class EnumerateCollectionBlock : public ExecutionBlock {
public:
EnumerateCollectionBlock (EnumerateCollectionPlan const* ep)
: ExecutionBlock(ep) {
: ExecutionBlock(ep), _input(nullptr) {
}
~EnumerateCollectionBlock () {
@ -156,11 +200,17 @@ namespace triagens {
int initialize () {
// TODO: this is very very inefficient
// it must be implemented properly for production
int res = ExecutionBlock::initialize();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
auto p = reinterpret_cast<EnumerateCollectionPlan const*>(_exePlan);
V8ReadTransaction trx(p->_vocbase, p->_collname);
int res = trx.begin();
res = trx.begin();
vector<TRI_doc_mptr_t*> docs;
res = trx.read(docs);
@ -168,32 +218,63 @@ namespace triagens {
auto shaper = trx.documentCollection()->getShaper();
_allDocs.clear();
for (size_t i = 0; i < n; ++i) {
TRI_shaped_json_t shaped;
TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, docs[i]->getDataPtr());
triagens::basics::Json json(TRI_UNKNOWN_MEM_ZONE, TRI_JsonShapedJson(shaper, &shaped));
_buffer.push_back(new AqlValue(json));
_allDocs.push_back(new Json(TRI_UNKNOWN_MEM_ZONE,
TRI_JsonShapedJson(shaper, &shaped)));
}
res = trx.finish(res);
_pos = 0;
if (_allDocs.size() == 0) {
_done = true;
}
_input = nullptr;
return res;
}
int shutdown () {
return TRI_ERROR_NO_ERROR;
int res = ExecutionBlock::shutdown(); // Tell all dependencies
_allDocs.clear();
return res;
}
AqlValue* getOne () {
AqlItem* getOne () {
std::cout << "getOne of EnumerateCollectionBlock" << std::endl;
if (_buffer.empty()) {
if (_done) {
return nullptr;
}
auto value = _buffer.front();
_buffer.pop_front();
return value;
if (_input == nullptr) {
_input = _dependencies[0]->getOne();
if (_input == nullptr) {
_done = true;
return nullptr;
}
_pos = 0;
if (_allDocs.size() == 0) {
_done = true;
return nullptr;
}
}
AqlItem* res = new AqlItem(_input, 1);
res->setValue(0,0,new AqlValue(_allDocs[_pos]));
if (++_pos >= _allDocs.size()) {
_input = nullptr; // get a new item next time
}
return res;
}
private:
vector<Json*> _allDocs;
size_t _pos;
AqlItem* _input;
bool _done;
};
class RootBlock : public ExecutionBlock {
@ -208,7 +289,7 @@ namespace triagens {
~RootBlock () {
}
AqlValue* getOne () {
AqlItem* getOne () {
std::cout << "getOne of RootBlock" << std::endl;
return _dependencies[0]->getOne();
}

View File

@ -91,6 +91,31 @@ void ExecutionPlan::appendAsString (std::string& st, int indent) {
st.push_back('>');
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of SingletonPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson, for SingletonPlan
////////////////////////////////////////////////////////////////////////////////
Json SingletonPlan::toJson (TRI_memory_zone_t* zone) const {
Json json(ExecutionPlan::toJson(zone)); // call base class method
if (json.isEmpty()) {
return json;
}
// Now put info about number of vars:
try {
json("nrVariables", Json(_nrVars));
}
catch (std::exception& e) {
return Json();
}
// And return it:
return json;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of EnumerateCollectionPlan
// -----------------------------------------------------------------------------
@ -112,7 +137,8 @@ Json EnumerateCollectionPlan::toJson (TRI_memory_zone_t* zone) const {
else {
json("vocbase", Json(_vocbase->_name));
}
json("collection", Json(_collname));
json("collection", Json(_collname))
("nrVariables", Json(_nrVars));
}
catch (std::exception& e) {
return Json();
@ -240,7 +266,7 @@ void testExecutionPlans () {
std::cout << a.toString() << std::endl;
std::cout << "Got here" << std::endl;
auto ec = new EnumerateCollectionPlan(nullptr, "guck");
auto ec = new EnumerateCollectionPlan(nullptr, "guck", 1);
Json jjj(ec->toJson());
cout << jjj.toString() << endl;
auto li = new LimitPlan(12, 17);

View File

@ -56,6 +56,7 @@ namespace triagens {
enum NodeType {
ILLEGAL,
SINGLETON,
ENUMERATE_COLLECTION,
INDEX_RANGE,
STATIC_LIST,
@ -218,6 +219,71 @@ namespace triagens {
};
// -----------------------------------------------------------------------------
// --SECTION-- class SingletonPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief class SingletonPlan, derived from ExecutionPlan
////////////////////////////////////////////////////////////////////////////////
class SingletonPlan : public ExecutionPlan {
friend class SingletonBlock;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor with a vocbase and a collection name
////////////////////////////////////////////////////////////////////////////////
public:
SingletonPlan (int32_t nrvars)
: ExecutionPlan(), _nrVars(nrvars) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the type of the node
////////////////////////////////////////////////////////////////////////////////
virtual NodeType getType () const {
return SINGLETON;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the type of the node as a string
////////////////////////////////////////////////////////////////////////////////
virtual std::string getTypeString () const {
return std::string("SingletonPlan");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON
////////////////////////////////////////////////////////////////////////////////
virtual triagens::basics::Json toJson (
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief clone execution plan recursively
////////////////////////////////////////////////////////////////////////////////
virtual ExecutionPlan* clone () const {
auto c = new SingletonPlan(_nrVars);
cloneDependencies(c);
return static_cast<ExecutionPlan*>(c);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief we need to know how many variables we have in this scope
////////////////////////////////////////////////////////////////////////////////
private:
int32_t _nrVars;
};
// -----------------------------------------------------------------------------
// --SECTION-- class EnumerateCollectionPlan
// -----------------------------------------------------------------------------
@ -236,8 +302,11 @@ namespace triagens {
public:
EnumerateCollectionPlan (TRI_vocbase_t* vocbase, std::string collname)
: ExecutionPlan(), _vocbase(vocbase), _collname(collname) {
EnumerateCollectionPlan (TRI_vocbase_t* vocbase,
std::string collname,
int32_t nrVars)
: ExecutionPlan(), _vocbase(vocbase), _collname(collname),
_nrVars(nrVars) {
}
////////////////////////////////////////////////////////////////////////////////
@ -268,15 +337,11 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
virtual ExecutionPlan* clone () const {
auto c = new EnumerateCollectionPlan(_vocbase, _collname);
auto c = new EnumerateCollectionPlan(_vocbase, _collname, _nrVars);
cloneDependencies(c);
return static_cast<ExecutionPlan*>(c);
}
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief we need to know the database and the collection
////////////////////////////////////////////////////////////////////////////////
@ -285,6 +350,7 @@ namespace triagens {
TRI_vocbase_t* _vocbase;
std::string _collname;
int32_t _nrVars;
};

View File

@ -37,88 +37,147 @@ namespace triagens {
namespace aql {
// -----------------------------------------------------------------------------
// --SECTION-- AqlValues
// --SECTION-- AqlDoc
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief struct AqlValue, used to pipe documents through executions
/// the execution engine keeps one AqlValue struct for each document
/// that is piped through the engine. Note that the document can exist
/// in one of two formats throughout its lifetime in the engine.
/// When it resides originally in the WAl or a datafile, it stays
/// there unchanged and we only store a (pointer to) a copy of the
/// TRI_doc_mptr_t struct. Sometimes, when it is modified (or created
/// on the fly anyway), we keep the document as a TRI_json_t, wrapped
/// by a Json struct. That is, the following struct has the following
/// invariant:
/// Either the whole struct is empty and thus _json is empty and _mptr
/// is a nullptr. Otherwise, either _json is empty and _mptr is not a
/// nullptr, or _json is non-empty and _mptr is anullptr.
/// Additionally, the struct contains another TRI_json_t holding
/// the current state of the LET variables (and possibly some other
/// computations). This is the _vars attribute.
/// Note that both Json subobjects are constructed as AUTOFREE.
////////////////////////////////////////////////////////////////////////////////
struct AqlItem;
struct AqlValue {
triagens::basics::Json _json;
TRI_doc_mptr_t* _mptr;
triagens::basics::Json _vars;
////////////////////////////////////////////////////////////////////////////////
/// @brief convenience constructors
////////////////////////////////////////////////////////////////////////////////
enum AqlValueType {
JSON,
DOCVEC,
RANGE
};
AqlValue ()
: _json(), _mptr(nullptr), _vars() {
struct Range {
int64_t _low;
int64_t _high;
Range(int64_t low, int64_t high) : _low(low), _high(high) {}
};
union {
triagens::basics::Json* _json;
std::vector<AqlItem*>* _vector;
Range _range;
};
AqlValueType _type;
AqlValue (triagens::basics::Json* json)
: _json(json), _type(JSON) {
}
AqlValue (TRI_doc_mptr_t* mptr)
: _json(), _mptr(mptr), _vars() {
AqlValue (std::vector<AqlItem*>* vector)
: _vector(vector), _type(DOCVEC) {
}
AqlValue (triagens::basics::Json json)
: _json(json), _mptr(nullptr), _vars() {
AqlValue (int64_t low, int64_t high)
: _range(low, high), _type(RANGE) {
}
~AqlValue () {
switch (_type) {
case JSON:
delete _json;
break;
case DOCVEC:
delete _vector;
break;
case RANGE:
break;
}
}
std::string toString () {
switch (_type) {
case JSON:
return _json->toString();
case DOCVEC:
return "I am a DOCVEC.";
case RANGE:
std::stringstream s;
s << "I am a range: " << _range._low << " .. " << _range._high;
return s.str();
}
}
};
struct AqlItem {
AqlItem* _outer;
int32_t _refcount;
int32_t _nrvars;
AqlValue** _vars;
AqlItem (int nrvars)
: _outer(nullptr), _refcount(1), _nrvars(nrvars) {
if (nrvars > 0) {
_vars = new AqlValue* [nrvars];
}
else {
_vars = nullptr;
}
}
AqlItem (AqlItem* outer, int nrvars)
: _outer(outer), _refcount(1), _nrvars(nrvars) {
outer->_refcount++;
if (nrvars > 0) {
_vars = new AqlValue* [nrvars];
for (int i = 0; i < nrvars; i++) {
_vars[i] = nullptr;
}
}
else {
_vars = nullptr;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~AqlValue () {
~AqlItem () {
if (_outer != nullptr) {
_outer->_refcount--;
if (_outer->_refcount == 0) {
delete _outer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a string representation of the value
////////////////////////////////////////////////////////////////////////////////
std::string toString () const {
std::string out;
if (! _json.isEmpty()) {
out += _json.toString();
_outer = nullptr;
}
else if (_mptr != nullptr) {
out.append("got a master pointer");
if (_vars != nullptr) {
for (int i = 0; i < _nrvars; i++) {
delete _vars[i];
}
if (! _vars.isEmpty()) {
out += _vars.toString();
delete[] _vars;
}
return out;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getValue, get the current value of a variable or attribute
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json getValue (std::string name);
AqlValue* getValue (int up, int index) {
AqlItem* p = this;
for (int i = 0; i < up; i++) {
p = p->_outer;
}
return p->_vars[index];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief setValue, set the current value of a variable or attribute
////////////////////////////////////////////////////////////////////////////////
void setValue (std::string name, triagens::basics::Json json);
void setValue (int up, int index, AqlValue* zeug) {
AqlItem* p = this;
for (int i = 0; i < up; i++) {
p = p->_outer;
}
p->_vars[index] = zeug;
}
};
@ -173,7 +232,7 @@ namespace triagens {
/// @brief execute the expression
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json execute (AqlValue* aqldoc);
AqlValue* execute (AqlItem* aqldoc);
////////////////////////////////////////////////////////////////////////////////
/// @brief private members

View File

@ -5414,7 +5414,9 @@ static v8::Handle<v8::Value> JS_PengAql (v8::Arguments const& argv) {
TRI_V8_EXCEPTION_USAGE(scope, "AQL_PENG()");
}
triagens::aql::ExecutionPlan* enumPlan = new triagens::aql::EnumerateCollectionPlan(vocbase, "fuxx");
triagens::aql::ExecutionPlan* singlePlan = new triagens::aql::SingletonPlan(0);
triagens::aql::ExecutionPlan* enumPlan = new triagens::aql::EnumerateCollectionPlan(vocbase, "fuxx", 1);
enumPlan->addDependency(singlePlan);
triagens::aql::ExecutionPlan* rootPlan = new triagens::aql::RootPlan();
rootPlan->addDependency(enumPlan);
@ -5423,10 +5425,10 @@ static v8::Handle<v8::Value> JS_PengAql (v8::Arguments const& argv) {
exec->initialize();
exec->execute();
triagens::aql::AqlValue* value;
triagens::aql::AqlItem* value;
while (nullptr != (value = exec->getOne())) {
std::cout << "Peng" << std::endl;
std::cout << value->toString() << std::endl;
std::cout << value->getValue(0,0)->toString() << std::endl;
delete value;
}