1
0
Fork 0

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

This commit is contained in:
Willi Goesgens 2014-09-11 13:25:18 +02:00
commit 0225311f2d
29 changed files with 1091 additions and 246 deletions

View File

@ -1,6 +1,16 @@
v2.3.0 (XXXX-XX-XX) v2.3.0 (XXXX-XX-XX)
------------------- -------------------
* changed return value of Foxx.applicationContext#collectionName:
Previously, the function could return invalid collection names because
invalid characters were not replaced in the application name prefix, only
in the collection name passed.
Now, the function replaces invalid characters also in the application name
prefix, which might to slightly different results for application names that
contained any characters outside the ranges [a-z], [A-Z] and [0-9].
* prevent XSS in AQL editor and logs view * prevent XSS in AQL editor and logs view
* integrated tutorial into ArangoShell and web interface * integrated tutorial into ArangoShell and web interface
@ -77,9 +87,40 @@ v2.3.0 (XXXX-XX-XX)
storing JavaScript date objects in the database in a sensible manner. storing JavaScript date objects in the database in a sensible manner.
v2.2.3 (2014-XX-XX) v2.2.4 (2014-XX-XX)
------------------- -------------------
* fixed issue #1016: AQL editor bug
* fixed issue #1014: WITHIN function returns wrong distance
* fixed AQL shortest path calculation in function `GRAPH_SHORTEST_PATH` to return
complete vertex objects instead of just vertex ids
* allow changing of attributes of documents stored in server-side JavaScript variables
Previously, the following did not work:
var doc = db.collection.document(key);
doc._key = "abc"; // overwriting internal attributes not supported
doc.value = 123; // overwriting existing attributes not supported
Now, modifying documents stored in server-side variables (e.g. `doc` in the above case)
is supported. Modifying the variables will not update the documents in the database,
but will modify the JavaScript object (which can be written back to the database using
`db.collection.update` or `db.collection.replace`)
* fixed issue #997: arangoimp apparently doesn't support files >2gig on Windows
large file support (requires using `_stat64` instead of `stat`) is now supported on
Windows
v2.2.3 (2014-09-02)
-------------------
* added `around` for Foxx controller
* added `type` option for HTTP API `GET /_api/document?collection=...` * added `type` option for HTTP API `GET /_api/document?collection=...`
This allows controlling the type of results to be returned. By default, paths to This allows controlling the type of results to be returned. By default, paths to

View File

@ -49,6 +49,7 @@ migrations will also be detailed here.
* Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` is now deprecated, it will raise a warning if you use it. To suppress the warning, please start `arangod` with the option `--server.default-api-compatibility 20200`. Please use `graphName` instead. * Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` is now deprecated, it will raise a warning if you use it. To suppress the warning, please start `arangod` with the option `--server.default-api-compatibility 20200`. Please use `graphName` instead.
* Replication: the methods `logger.start`, `logger.stop` and `logger.properties` are now deprecated. Using them will raise a warning. * Replication: the methods `logger.start`, `logger.stop` and `logger.properties` are now deprecated. Using them will raise a warning.
* Replication: the HTTP methods `PUT /_api/replication/logger-start`, `PUT /_api/replication/logger-stop`, `GET /_api/replication/logger-config` and `PUT /_api/replication/logger-config` are now deprecated. Using them will raise a warning. * Replication: the HTTP methods `PUT /_api/replication/logger-start`, `PUT /_api/replication/logger-stop`, `GET /_api/replication/logger-config` and `PUT /_api/replication/logger-config` are now deprecated. Using them will raise a warning.
* General-Graph: In the module `org/arangodb/general-graph` the functions `_undirectedRelation` and `_directedRelation` is no longer suggested, they will be deprecated int the next version. Both functions have been unified to `_relation`.
## 2.4 ## 2.4
@ -68,6 +69,8 @@ migrations will also be detailed here.
* Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` is no longer available by default. If you still want to use it, please start `arangod` with the option `--server.default-api-compatibility 20200`. Please use `graphName` instead. * Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` is no longer available by default. If you still want to use it, please start `arangod` with the option `--server.default-api-compatibility 20200`. Please use `graphName` instead.
* Replication: the methods `logger.start`, `logger.stop` and `logger.properties` are no longer available. * Replication: the methods `logger.start`, `logger.stop` and `logger.properties` are no longer available.
* Replication: the HTTP methods `PUT /_api/replication/logger-start`, `PUT /_api/replication/logger-stop`, `GET /_api/replication/logger-config` and `PUT /_api/replication/logger-config` are no longer available. * Replication: the HTTP methods `PUT /_api/replication/logger-start`, `PUT /_api/replication/logger-stop`, `GET /_api/replication/logger-config` and `PUT /_api/replication/logger-config` are no longer available.
To suppress the warning, please start `arangod` with the option `--server.default-api-compatibility 20200`.
* General-Graph: In the module `org/arangodb/general-graph` the functions `_undirectedRelation` and `_directedRelation` are deprecated and will throw an error if you use them. Both functions have been unified to `_relation`.
## 2.5 ## 2.5
@ -85,3 +88,4 @@ migrations will also be detailed here.
* Traversal: The usage of the traversal datasource `collectionDatasourceFactory` has been removed entirely. Please use `generalGraphDatasourceFactory` instead. * Traversal: The usage of the traversal datasource `collectionDatasourceFactory` has been removed entirely. Please use `generalGraphDatasourceFactory` instead.
* Http: The api `_api/graph` has been removed entirely. Please use the general graph api `_api/gharial` instead. * Http: The api `_api/graph` has been removed entirely. Please use the general graph api `_api/gharial` instead.
* Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` has been removed entirely. Please use `graphName` instead. * Http: In `POST _api/traversal` the usage of the body parameter `edgeCollection` has been removed entirely. Please use `graphName` instead.
* General-Graph: In the module `org/arangodb/general-graph` the functions `_undirectedRelation` and `_directedRelation` are no longer available by default, if you still want to use them start `arangod` with the option `--server.default-api-compatibility 20300`. Both functions have been unified to `_relation`.

View File

@ -8,7 +8,7 @@ In order to create a non empty graph the functionality to create edge definition
!SECTION Edge Definitions !SECTION Edge Definitions
An edge definition is a directed or undirected relation of a graph. Each graph can have arbitrary many relations defined within the edge definitions array. An edge definition is always a directed relation of a graph. Each graph can have arbitrary many relations defined within the edge definitions array.
!SUBSECTION Initialize the list !SUBSECTION Initialize the list
@ -18,12 +18,27 @@ An edge definition is a directed or undirected relation of a graph. Each graph c
@startDocuBlock JSF_general_graph_extend_edge_definitions @startDocuBlock JSF_general_graph_extend_edge_definitions
!SUBSUBSECTION Relation
@startDocuBlock JSF_general_graph_relation
!SUBSUBSECTION Undirected Relation !SUBSUBSECTION Undirected Relation
**Warning: Deprecated**
This function is deprecated and will be removed soon.
Please use [Relation](../General-Graphs/Management.html#relation) instead.
@startDocuBlock JSF_general_graph_undirectedRelation @startDocuBlock JSF_general_graph_undirectedRelation
!SUBSUBSECTION Directed Relation !SUBSUBSECTION Directed Relation
**Warning: Deprecated**
This function is deprecated and will be removed soon.
Please use [Relation](../General-Graphs/Management.html#relation) instead.
@startDocuBlock JSF_general_graph_directedRelation @startDocuBlock JSF_general_graph_directedRelation
!SECTION Create a graph !SECTION Create a graph

View File

@ -393,6 +393,8 @@ distclean-local:
clean-local: clean-local:
rm -rf $(CLEANUP) rm -rf $(CLEANUP)
rm -rf `find -name \*.gcno`
rm -rf `find -name \*.gcda`
superclean: clean superclean: clean
rm -rf arangod/*/.deps lib/*/.deps Makefile rm -rf arangod/*/.deps lib/*/.deps Makefile

View File

@ -99,6 +99,27 @@ void AqlValue::destroy () {
_type = EMPTY; _type = EMPTY;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief get the name of an AqlValue type
////////////////////////////////////////////////////////////////////////////////
std::string AqlValue::getTypeString () const {
switch (_type) {
case JSON:
return "json";
case SHAPED:
return "shaped";
case DOCVEC:
return "docvec";
case RANGE:
return "range";
case EMPTY:
return "empty";
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief clone for recursive copying /// @brief clone for recursive copying
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -242,7 +263,6 @@ bool AqlValue::isArray () const {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue /// @brief get a string representation of the AqlValue
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -578,10 +598,15 @@ Json AqlValue::extractListMember (AQL_TRANSACTION_V8* trx,
case RANGE: { case RANGE: {
TRI_ASSERT(_range != nullptr); TRI_ASSERT(_range != nullptr);
size_t const n = _range->size(); size_t const n = _range->size();
size_t const p = static_cast<size_t>(position);
if (p < n) { if (position < 0) {
return Json(static_cast<double>(_range->at(p))); // a negative position is allowed
position = static_cast<int64_t>(n) + position;
}
if (position >= 0 && position < static_cast<int64_t>(n)) {
// only look up the value if it is within list bounds
return Json(static_cast<double>(_range->at(static_cast<size_t>(position))));
} }
break; // fall-through to returning null break; // fall-through to returning null
} }

View File

@ -144,6 +144,12 @@ namespace triagens {
void destroy (); void destroy ();
////////////////////////////////////////////////////////////////////////////////
/// @brief get the name of an AqlValue type
////////////////////////////////////////////////////////////////////////////////
std::string getTypeString () const;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief clone for recursive copying /// @brief clone for recursive copying
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -181,6 +187,32 @@ namespace triagens {
std::string toString () const; std::string toString () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief get the numeric value of an AqlValue
/// this will fail if the value is not a number
////////////////////////////////////////////////////////////////////////////////
template<typename T>
T toNumber () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
TRI_ASSERT(TRI_IsNumberJson(json));
return static_cast<T>(json->_value._number);
}
case SHAPED:
case DOCVEC:
case RANGE:
case EMPTY: {
// cannot convert these types
return 0;
}
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue /// @brief get a string representation of the AqlValue
/// this will fail if the value is not a string /// this will fail if the value is not a string

View File

@ -571,12 +571,18 @@ bool AstNode::isSimple () const {
if (type == NODE_TYPE_FCALL) { if (type == NODE_TYPE_FCALL) {
// some functions have C++ handlers // some functions have C++ handlers
// check if the called function is one of them
auto func = static_cast<Function*>(getData()); auto func = static_cast<Function*>(getData());
TRI_ASSERT(func != nullptr); TRI_ASSERT(func != nullptr);
return (func->implementation != nullptr && getMember(0)->isSimple()); return (func->implementation != nullptr && getMember(0)->isSimple());
} }
if (type == NODE_TYPE_RANGE) {
// a range is simple if both bounds are simple
return (getMember(0)->isSimple() && getMember(1)->isSimple());
}
return false; return false;
} }

View File

@ -1023,7 +1023,7 @@ void IndexRangeBlock::readSkiplistIndex () {
skiplistOperator = TRI_CreateIndexOperator(TRI_EQ_INDEX_OPERATOR, nullptr, skiplistOperator = TRI_CreateIndexOperator(TRI_EQ_INDEX_OPERATOR, nullptr,
nullptr, parameters.copy().steal(), shaper, nullptr, i, nullptr); nullptr, parameters.copy().steal(), shaper, nullptr, i, nullptr);
} }
if (!range._low._undefined) { if (! range._low._undefined) {
auto op = range._low.toIndexOperator(false, parameters.copy(), shaper); auto op = range._low.toIndexOperator(false, parameters.copy(), shaper);
if (skiplistOperator != nullptr) { if (skiplistOperator != nullptr) {
skiplistOperator = TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR, skiplistOperator = TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR,
@ -1033,7 +1033,7 @@ void IndexRangeBlock::readSkiplistIndex () {
skiplistOperator = op; skiplistOperator = op;
} }
} }
if (!range._high._undefined) { if (! range._high._undefined) {
auto op = range._high.toIndexOperator(true, parameters.copy(), shaper); auto op = range._high.toIndexOperator(true, parameters.copy(), shaper);
if (skiplistOperator != nullptr) { if (skiplistOperator != nullptr) {
skiplistOperator = TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR, skiplistOperator = TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR,
@ -1133,7 +1133,6 @@ void IndexRangeBlock::readHashIndex () {
} }
} }
//std::cout << "PID: " << pid << ", NAME: " << name << "\n";
} }
}; };
@ -1360,7 +1359,7 @@ size_t EnumerateListBlock::skipSome (size_t atLeast, size_t atMost) {
break; break;
} }
case AqlValue::RANGE: { case AqlValue::RANGE: {
sizeInVar = inVarReg._range->_high - inVarReg._range->_low + 1; sizeInVar = inVarReg._range->size();
break; break;
} }
case AqlValue::DOCVEC: { case AqlValue::DOCVEC: {
@ -1412,7 +1411,7 @@ AqlValue EnumerateListBlock::getAqlValue (AqlValue inVarReg) {
return AqlValue(new Json(inVarReg._json->at(_index++).copy())); return AqlValue(new Json(inVarReg._json->at(_index++).copy()));
} }
case AqlValue::RANGE: { case AqlValue::RANGE: {
return AqlValue(new Json(static_cast<double>(inVarReg._range->_low + _index++))); return AqlValue(new Json(static_cast<double>(inVarReg._range->at(_index++))));
} }
case AqlValue::DOCVEC: { // incoming doc vec has a single column case AqlValue::DOCVEC: { // incoming doc vec has a single column
AqlValue out = inVarReg._vector->at(_thisblock)->getValue(_index - AqlValue out = inVarReg._vector->at(_thisblock)->getValue(_index -

View File

@ -366,7 +366,7 @@ Variable* ExecutionNode::varFromJson (Ast* ast,
} }
else { else {
std::string msg; std::string msg;
msg += "Mandatory variable \"" + std::string(variableName) + "\"not found."; msg += "Mandatory variable \"" + std::string(variableName) + "\" not found.";
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, msg.c_str()); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, msg.c_str());
} }
} }
@ -406,10 +406,8 @@ Json ExecutionNode::toJsonHelperGeneric (triagens::basics::Json& nodes,
json("parents", parents); json("parents", parents);
} }
json("id", Json(static_cast<double>(id()))); json("id", Json(static_cast<double>(id())));
if (_estimatedCost != 0.0) {
json("estimatedCost", Json(_estimatedCost)); json("estimatedCost", Json(_estimatedCost));
}
return json; return json;
} }

View File

@ -346,6 +346,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
else if (node->type == NODE_TYPE_FCALL) { else if (node->type == NODE_TYPE_FCALL) {
// some functions have C++ handlers // some functions have C++ handlers
// check if the called function has one
auto func = static_cast<Function*>(node->getData()); auto func = static_cast<Function*>(node->getData());
TRI_ASSERT(func->implementation != nullptr); TRI_ASSERT(func->implementation != nullptr);
@ -358,6 +359,21 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
return res2; return res2;
} }
else if (node->type == NODE_TYPE_RANGE) {
TRI_document_collection_t const* myCollection = nullptr;
auto low = node->getMember(0);
auto high = node->getMember(1);
AqlValue resultLow = executeSimpleExpression(low, &myCollection, trx, docColls, argv, startPos, vars, regs);
AqlValue resultHigh = executeSimpleExpression(high, &myCollection, trx, docColls, argv, startPos, vars, regs);
if (! resultLow.isNumber() || ! resultHigh.isNumber()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid data type for range");
}
return AqlValue(resultLow.toNumber<int64_t>(), resultHigh.toNumber<int64_t>());
}
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled type in simple expression"); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled type in simple expression");
} }

View File

@ -84,6 +84,7 @@ Query::Query (TRI_vocbase_t* vocbase,
_queryJson(queryStruct), _queryJson(queryStruct),
_type(Type), _type(Type),
_bindParameters(nullptr), _bindParameters(nullptr),
_options(nullptr),
_collections(vocbase), _collections(vocbase),
_strings() { _strings() {
@ -99,6 +100,7 @@ Query::Query (TRI_vocbase_t* vocbase,
Query::~Query () { Query::~Query () {
if (_options != nullptr) { if (_options != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _options); TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _options);
_options = nullptr;
} }
if (_executor != nullptr) { if (_executor != nullptr) {
@ -351,7 +353,7 @@ QueryResult Query::parse () {
/// @brief explain an AQL query /// @brief explain an AQL query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QueryResult Query::explain (bool returnAllPlans) { QueryResult Query::explain () {
try { try {
ExecutionPlan* plan; ExecutionPlan* plan;
Parser parser(this); Parser parser(this);
@ -391,14 +393,14 @@ QueryResult Query::explain (bool returnAllPlans) {
QueryResult result(TRI_ERROR_NO_ERROR); QueryResult result(TRI_ERROR_NO_ERROR);
if (returnAllPlans) { if (allPlans()) {
triagens::basics::Json out(triagens::basics::Json::List); triagens::basics::Json out(triagens::basics::Json::List);
auto plans = opt.getPlans(); auto plans = opt.getPlans();
for (auto it : plans) { for (auto it : plans) {
TRI_ASSERT(it != nullptr); TRI_ASSERT(it != nullptr);
out.add(it->toJson(TRI_UNKNOWN_MEM_ZONE, false)); out.add(it->toJson(TRI_UNKNOWN_MEM_ZONE, verbosePlans()));
} }
result.json = out.steal(); result.json = out.steal();
@ -408,7 +410,7 @@ QueryResult Query::explain (bool returnAllPlans) {
plan = opt.stealBest(); // Now we own the best one again plan = opt.stealBest(); // Now we own the best one again
TRI_ASSERT(plan != nullptr); TRI_ASSERT(plan != nullptr);
result.json = plan->toJson(TRI_UNKNOWN_MEM_ZONE, false).steal(); result.json = plan->toJson(TRI_UNKNOWN_MEM_ZONE, verbosePlans()).steal();
delete plan; delete plan;
} }
@ -500,14 +502,30 @@ char* Query::registerString (std::string const& p,
// --SECTION-- private methods // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch a boolean value from the options
////////////////////////////////////////////////////////////////////////////////
bool Query::getBooleanOption (char const* option, bool defaultValue) const {
if (! TRI_IsArrayJson(_options)) {
return defaultValue;
}
TRI_json_t const* valueJson = TRI_LookupArrayJson(_options, option);
if (! TRI_IsBooleanJson(valueJson)) {
return defaultValue;
}
return valueJson->_value._boolean;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief neatly format transaction errors to the user. /// @brief neatly format transaction errors to the user.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QueryResult Query::transactionError (int errorCode, AQL_TRANSACTION_V8 const& trx) QueryResult Query::transactionError (int errorCode, AQL_TRANSACTION_V8 const& trx) const
{ {
std::string err; std::string err(TRI_errno_string(errorCode));
err += std::string(TRI_errno_string(errorCode));
auto detail = trx.getErrorData(); auto detail = trx.getErrorData();
if (detail.size() > 0) { if (detail.size() > 0) {
@ -519,7 +537,6 @@ QueryResult Query::transactionError (int errorCode, AQL_TRANSACTION_V8 const& tr
return QueryResult(errorCode, err); return QueryResult(errorCode, err);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief read the "optimizer.rules" section from the options /// @brief read the "optimizer.rules" section from the options
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -155,6 +155,22 @@ namespace triagens {
return _queryLength; return _queryLength;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief should we return verbose plans?
////////////////////////////////////////////////////////////////////////////////
bool verbosePlans () const {
return getBooleanOption("verbosePlans", false);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief should we return all plans?
////////////////////////////////////////////////////////////////////////////////
bool allPlans () const {
return getBooleanOption("allPlans", false);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief extract a region from the query /// @brief extract a region from the query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -185,7 +201,7 @@ namespace triagens {
/// @brief explain an AQL query /// @brief explain an AQL query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QueryResult explain (bool); QueryResult explain ();
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get v8 executor /// @brief get v8 executor
@ -214,6 +230,13 @@ namespace triagens {
// --SECTION-- private methods // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch a boolean value from the options
////////////////////////////////////////////////////////////////////////////////
bool getBooleanOption (char const*,
bool) const;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief read the "optimizer.rules" section from the options /// @brief read the "optimizer.rules" section from the options
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -224,7 +247,7 @@ namespace triagens {
/// @brief neatly format transaction errors to the user. /// @brief neatly format transaction errors to the user.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QueryResult transactionError (int errorCode, AQL_TRANSACTION_V8 const& trx); QueryResult transactionError (int errorCode, AQL_TRANSACTION_V8 const& trx) const;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private variables // --SECTION-- private variables

View File

@ -44,6 +44,8 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct Range { struct Range {
Range () = delete;
Range (int64_t low, Range (int64_t low,
int64_t high) int64_t high)
: _low(low), : _low(low),

View File

@ -650,7 +650,9 @@ void ClusterInfo::loadPlannedCollections (bool acquireLock) {
_shards.insert( _shards.insert(
make_pair(collection,shared_ptr<vector<string> >(shards))); make_pair(collection,shared_ptr<vector<string> >(shards)));
// insert the collection into the existing map // insert the collection into the existing map, insert it under its
// ID as well as under its name, so that a lookup can be done with
// either of the two.
(*it2).second.insert(std::make_pair(collection, collectionData)); (*it2).second.insert(std::make_pair(collection, collectionData));
(*it2).second.insert(std::make_pair(collectionData->name(), (*it2).second.insert(std::make_pair(collectionData->name(),
@ -687,7 +689,7 @@ shared_ptr<CollectionInfo> ClusterInfo::getCollection
AllCollections::const_iterator it = _collections.find(databaseID); AllCollections::const_iterator it = _collections.find(databaseID);
if (it != _collections.end()) { if (it != _collections.end()) {
// look up collection by id // look up collection by id (or by name)
DatabaseCollections::const_iterator it2 = (*it).second.find(collectionID); DatabaseCollections::const_iterator it2 = (*it).second.find(collectionID);
if (it2 != (*it).second.end()) { if (it2 != (*it).second.end()) {

View File

@ -810,7 +810,8 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief ask about a collection /// @brief ask about a collection
/// If it is not found in the cache, the cache is reloaded once. /// If it is not found in the cache, the cache is reloaded once. The second
/// argument can be a collection ID or a collection name (both cluster-wide).
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
shared_ptr<CollectionInfo> getCollection (DatabaseID const&, shared_ptr<CollectionInfo> getCollection (DatabaseID const&,

View File

@ -165,16 +165,24 @@ namespace triagens {
(&_vocbase->_collectionsById, &cid)); (&_vocbase->_collectionsById, &cid));
if (nullptr != found) { if (nullptr != found) {
if (found->_planId == 0) {
// DBserver local case
char* n = TRI_GetCollectionNameByIdVocBase(_vocbase, cid);
if (0 != n) {
name = n;
TRI_Free(TRI_UNKNOWN_MEM_ZONE, n);
}
}
else {
// DBserver case of a shard:
name = triagens::basics::StringUtils::itoa(found->_planId); name = triagens::basics::StringUtils::itoa(found->_planId);
shared_ptr<CollectionInfo> ci
= ClusterInfo::instance()->getCollection(found->_dbName,name);
name = ci->name(); // can be empty, if collection unknown
}
} }
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(_vocbase); TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(_vocbase);
if (! name.empty()) {
shared_ptr<CollectionInfo> ci
= ClusterInfo::instance()->getCollection(found->_dbName, name);
name = ci->name();
}
} }
else { else {
// exactly as in the non-cluster case // exactly as in the non-cluster case

View File

@ -889,7 +889,6 @@ static v8::Handle<v8::Value> JS_ExplainAql (v8::Arguments const& argv) {
} }
} }
bool returnAllPlans = false;
TRI_json_t* options = nullptr; TRI_json_t* options = nullptr;
if (argv.Length() > 2) { if (argv.Length() > 2) {
@ -901,18 +900,13 @@ static v8::Handle<v8::Value> JS_ExplainAql (v8::Arguments const& argv) {
TRI_V8_TYPE_ERROR(scope, "expecting object for <options>"); TRI_V8_TYPE_ERROR(scope, "expecting object for <options>");
} }
if (argv[2]->ToObject()->Has(TRI_V8_STRING("allPlans"))) {
// should we return all plans?
returnAllPlans = TRI_ObjectToBoolean(argv[2]->ToObject()->Get(TRI_V8_STRING("allPlans")));
}
options = TRI_ObjectToJson(argv[2]); options = TRI_ObjectToJson(argv[2]);
} }
// bind parameters will be freed by the query later // bind parameters will be freed by the query later
triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), parameters, options); triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), parameters, options);
auto queryResult = query.explain(returnAllPlans); auto queryResult = query.explain();
if (queryResult.code != TRI_ERROR_NO_ERROR) { if (queryResult.code != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION_FULL(scope, queryResult.code, queryResult.details); TRI_V8_EXCEPTION_FULL(scope, queryResult.code, queryResult.details);
@ -920,7 +914,7 @@ static v8::Handle<v8::Value> JS_ExplainAql (v8::Arguments const& argv) {
v8::Handle<v8::Object> result = v8::Object::New(); v8::Handle<v8::Object> result = v8::Object::New();
if (queryResult.json != nullptr) { if (queryResult.json != nullptr) {
if (returnAllPlans) { if (query.allPlans()) {
result->Set(TRI_V8_STRING("plans"), TRI_ObjectJson(queryResult.json)); result->Set(TRI_V8_STRING("plans"), TRI_ObjectJson(queryResult.json));
} }
else { else {

View File

@ -1303,6 +1303,9 @@ AQLGenerator.prototype.next = function() {
// --SECTION-- public functions // --SECTION-- public functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_undirectedRelation /// @startDocuBlock JSF_general_graph_undirectedRelation
/// @brief Define an undirected relation. /// @brief Define an undirected relation.
@ -1344,6 +1347,9 @@ AQLGenerator.prototype.next = function() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
var _undirectedRelation = function (relationName, vertexCollections) { var _undirectedRelation = function (relationName, vertexCollections) {
var err; var err;
if (arguments.length < 2) { if (arguments.length < 2) {
@ -1373,8 +1379,9 @@ var _undirectedRelation = function (relationName, vertexCollections) {
to: stringToArray(vertexCollections) to: stringToArray(vertexCollections)
}; };
}; };
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_directedRelation /// @startDocuBlock JSF_general_graph_directedRelation
/// @brief Define a directed relation. /// @brief Define a directed relation.
@ -1411,8 +1418,49 @@ var _undirectedRelation = function (relationName, vertexCollections) {
/// ///
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_relation
/// @brief Define a directed relation.
///
/// `graph_module._relation(relationName, fromVertexCollections, toVertexCollections)`
///
/// The *relationName* defines the name of this relation and references to the underlying edge collection.
/// The *fromVertexCollections* is an Array of document collections holding the start vertices.
/// The *toVertexCollections* is an Array of document collections holding the target vertices.
/// Relations are only allowed in the direction from any collection in *fromVertexCollections*
/// to any collection in *toVertexCollections*.
///
/// @PARAMS
///
/// @PARAM{relationName, string, required}
/// The name of the edge collection where the edges should be stored.
/// Will be created if it does not yet exist.
///
/// @PARAM{fromVertexCollections, array, required}
/// One or a list of collection names. Source vertices for the edges
/// have to be stored in these collections. Collections will be created if they do not exist.
///
/// @PARAM{toVertexCollections, array, required}
/// One or a list of collection names. Target vertices for the edges
/// have to be stored in these collections. Collections will be created if they do not exist.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphRelationDefinition}
/// var graph_module = require("org/arangodb/general-graph");
/// graph_module._relation("has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]);
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphRelationDefinitionSingle}
/// var graph_module = require("org/arangodb/general-graph");
/// graph_module._relation("has_bought", "Customer", "Product");
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
var _directedRelation = function ( var _relation = function (
relationName, fromVertexCollections, toVertexCollections) { relationName, fromVertexCollections, toVertexCollections) {
var err; var err;
if (arguments.length < 3) { if (arguments.length < 3) {
@ -1500,8 +1548,8 @@ var _listObjects = function() {
/// ///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitions} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitions}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// directed_relation = graph_module._directedRelation("lives_in", "user", "city"); /// directed_relation = graph_module._relation("lives_in", "user", "city");
/// undirected_relation = graph_module._undirectedRelation("knows", "user"); /// undirected_relation = graph_module._relation("knows", "user", "user");
/// edgedefinitions = graph_module._edgeDefinitions(directed_relation, undirected_relation); /// edgedefinitions = graph_module._edgeDefinitions(directed_relation, undirected_relation);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
/// ///
@ -1542,8 +1590,8 @@ var _edgeDefinitions = function () {
/// ///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitionsExtend} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitionsExtend}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// directed_relation = graph_module._directedRelation("lives_in", "user", "city"); /// directed_relation = graph_module._relation("lives_in", "user", "city");
/// undirected_relation = graph_module._undirectedRelation("knows", "user"); /// undirected_relation = graph_module._relation("knows", "user", "user");
/// edgedefinitions = graph_module._edgeDefinitions(directed_relation); /// edgedefinitions = graph_module._edgeDefinitions(directed_relation);
/// edgedefinitions = graph_module._extendEdgeDefinitions(undirected_relation); /// edgedefinitions = graph_module._extendEdgeDefinitions(undirected_relation);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
@ -1605,7 +1653,7 @@ var sortEdgeDefinition = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3}
/// ~ var graph_module = require("org/arangodb/general-graph"); /// ~ var graph_module = require("org/arangodb/general-graph");
/// ~ var graph = graph_module._create("myGraph"); /// ~ var graph = graph_module._create("myGraph");
/// var rel = graph_module._directedRelation("isCustomer", ["shop"], ["customer"]); /// var rel = graph_module._relation("isCustomer", ["shop"], ["customer"]);
/// graph._extendEdgeDefinitions(rel); /// graph._extendEdgeDefinitions(rel);
/// graph; /// graph;
/// ~ graph_module._drop("myGraph", true); /// ~ graph_module._drop("myGraph", true);
@ -1654,7 +1702,7 @@ var sortEdgeDefinition = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraph2} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraph2}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// | graph = graph_module._create("myGraph", /// | graph = graph_module._create("myGraph",
/// [graph_module._undirectedRelation("myRelation", ["male", "female"])], ["sessions"]); /// [graph_module._relation("myRelation", ["male", "female"])], ["sessions"]);
/// ~ graph_module._drop("myGraph", true); /// ~ graph_module._drop("myGraph", true);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
/// ///
@ -3900,8 +3948,8 @@ Graph.prototype._diameter = function(options) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__extendEdgeDefinitions} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__extendEdgeDefinitions}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._extendEdgeDefinitions(ed2); /// graph._extendEdgeDefinitions(ed2);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4081,8 +4129,8 @@ var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollectio
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__editEdgeDefinition} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__editEdgeDefinition}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var original = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var original = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var modified = graph_module._directedRelation("myEC1", ["myVC2"], ["myVC3"]); /// var modified = graph_module._relation("myEC1", ["myVC2"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [original]); /// var graph = graph_module._create("myGraph", [original]);
/// graph._editEdgeDefinitions(modified); /// graph._editEdgeDefinitions(modified);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4160,8 +4208,8 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinition} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinition}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1, ed2]); /// var graph = graph_module._create("myGraph", [ed1, ed2]);
/// graph._deleteEdgeDefinition("myEC1"); /// graph._deleteEdgeDefinition("myEC1");
/// db._collection("myEC1"); /// db._collection("myEC1");
@ -4173,8 +4221,8 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinitionWithDrop} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinitionWithDrop}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1, ed2]); /// var graph = graph_module._create("myGraph", [ed1, ed2]);
/// graph._deleteEdgeDefinition("myEC1", true); /// graph._deleteEdgeDefinition("myEC1", true);
/// db._collection("myEC1"); /// db._collection("myEC1");
@ -4258,7 +4306,7 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollection)
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__addVertexCollection} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__addVertexCollection}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4318,7 +4366,7 @@ Graph.prototype._addVertexCollection = function(vertexCollectionName, createColl
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__orphanCollections} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__orphanCollections}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// graph._orphanCollections(); /// graph._orphanCollections();
@ -4357,7 +4405,7 @@ Graph.prototype._orphanCollections = function() {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__removeVertexCollections} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__removeVertexCollections}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// graph._addVertexCollection("myVC4", true); /// graph._addVertexCollection("myVC4", true);
@ -4422,8 +4470,13 @@ Graph.prototype._PRINT = function(context) {
// --SECTION-- MODULE EXPORTS // --SECTION-- MODULE EXPORTS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/// Deprecated function (announced 2.3)
exports._undirectedRelation = _undirectedRelation; exports._undirectedRelation = _undirectedRelation;
exports._directedRelation = _directedRelation; /// Deprecated function (announced 2.3)
exports._directedRelation = function () {
return _relation.apply(this, arguments);
} ;
exports._relation = _relation;
exports._graph = _graph; exports._graph = _graph;
exports._edgeDefinitions = _edgeDefinitions; exports._edgeDefinitions = _edgeDefinitions;
exports._extendEdgeDefinitions = _extendEdgeDefinitions; exports._extendEdgeDefinitions = _extendEdgeDefinitions;
@ -4452,9 +4505,9 @@ exports._listObjects = _listObjects;
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example1} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example1}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// var edgeDefinitions = graph_module._edgeDefinitions(); /// var edgeDefinitions = graph_module._edgeDefinitions();
/// graph_module._extendEdgeDefinitions(edgeDefinitions, graph_module._undirectedRelation("friend_of", ["Customer"])); /// graph_module._extendEdgeDefinitions(edgeDefinitions, graph_module._relation("friend_of", "Customer", "Customer"));
/// | graph_module._extendEdgeDefinitions( /// | graph_module._extendEdgeDefinitions(
/// | edgeDefinitions, graph_module._directedRelation( /// | edgeDefinitions, graph_module._relation(
/// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"])); /// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]));
/// graph_module._create("myStore", edgeDefinitions); /// graph_module._create("myStore", edgeDefinitions);
/// ~ graph_module._drop("myStore"); /// ~ graph_module._drop("myStore");
@ -4469,7 +4522,7 @@ exports._listObjects = _listObjects;
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example2} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example2}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// | var edgeDefinitions = graph_module._edgeDefinitions( /// | var edgeDefinitions = graph_module._edgeDefinitions(
/// | graph_module._undirectedRelation("friend_of", ["Customer"]), graph_module._directedRelation( /// | graph_module._relation("friend_of", ["Customer"]), graph_module._relation(
/// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"])); /// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]));
/// graph_module._create("myStore", edgeDefinitions); /// graph_module._create("myStore", edgeDefinitions);
/// ~ graph_module._drop("myStore"); /// ~ graph_module._drop("myStore");

View File

@ -207,7 +207,6 @@
var inputEditor = ace.edit("aqlEditor"); var inputEditor = ace.edit("aqlEditor");
inputEditor.getSession().setMode("ace/mode/aql"); inputEditor.getSession().setMode("ace/mode/aql");
inputEditor.setFontSize("16px"); inputEditor.setFontSize("16px");
inputEditor.setOptions({fontFamily: "Courier New"});
inputEditor.commands.addCommand({ inputEditor.commands.addCommand({
name: "togglecomment", name: "togglecomment",
bindKey: {win: "Ctrl-Shift-C", linux: "Ctrl-Shift-C", mac: "Command-Shift-C"}, bindKey: {win: "Ctrl-Shift-C", linux: "Ctrl-Shift-C", mac: "Command-Shift-C"},

View File

@ -31,6 +31,7 @@
var FoxxController = require("org/arangodb/foxx").Controller, var FoxxController = require("org/arangodb/foxx").Controller,
controller = new FoxxController(applicationContext), controller = new FoxxController(applicationContext),
cluster = require("org/arangodb/cluster"),
ArangoError = require("org/arangodb").ArangoError, ArangoError = require("org/arangodb").ArangoError,
actions = require("org/arangodb/actions"), actions = require("org/arangodb/actions"),
Model = require("org/arangodb/foxx").Model, Model = require("org/arangodb/foxx").Model,
@ -42,6 +43,41 @@
toId = function(c, k) { toId = function(c, k) {
return c + "/" + k; return c + "/" + k;
}, },
collectionRepresentation = function(collection, showProperties, showCount, showFigures) {
var result = {};
result.id = collection._id;
result.name = collection.name();
result.isSystem = (result.name.charAt(0) === '_');
if (showProperties) {
var properties = collection.properties();
result.doCompact = properties.doCompact;
result.isVolatile = properties.isVolatile;
result.journalSize = properties.journalSize;
result.keyOptions = properties.keyOptions;
result.waitForSync = properties.waitForSync;
if (cluster.isCoordinator()) {
result.shardKeys = properties.shardKeys;
result.numberOfShards = properties.numberOfShards;
}
}
if (showCount) {
result.count = collection.count();
}
if (showFigures) {
var figures = collection.figures();
if (figures) {
result.figures = figures;
}
}
result.status = collection.status();
result.type = collection.type();
return result;
},
buildError = function(err, code) { buildError = function(err, code) {
return { return {
error: true, error: true,
@ -365,9 +401,17 @@
controller.get("/:graph/vertex", function(req, res) { controller.get("/:graph/vertex", function(req, res) {
var name = req.params("graph"); var name = req.params("graph");
var g = Graph._graph(name); var g = Graph._graph(name);
setResponse(res, "collections", _.map(g._vertexCollections(), function(c) { var mapFunc;
if (req.params("collectionObjects")) {
mapFunc = function(c) {
return collectionRepresentation(c, false, false, false);
};
} else {
mapFunc = function(c) {
return c.name(); return c.name();
}).sort(), actions.HTTP_OK); };
}
setResponse(res, "collections", _.map(g._vertexCollections(), mapFunc).sort(), actions.HTTP_OK);
}) })
.pathParam("graph", { .pathParam("graph", {
type: graphName type: graphName

View File

@ -1302,6 +1302,9 @@ AQLGenerator.prototype.next = function() {
// --SECTION-- public functions // --SECTION-- public functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_undirectedRelation /// @startDocuBlock JSF_general_graph_undirectedRelation
/// @brief Define an undirected relation. /// @brief Define an undirected relation.
@ -1343,6 +1346,9 @@ AQLGenerator.prototype.next = function() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
var _undirectedRelation = function (relationName, vertexCollections) { var _undirectedRelation = function (relationName, vertexCollections) {
var err; var err;
if (arguments.length < 2) { if (arguments.length < 2) {
@ -1372,8 +1378,9 @@ var _undirectedRelation = function (relationName, vertexCollections) {
to: stringToArray(vertexCollections) to: stringToArray(vertexCollections)
}; };
}; };
////////////////////////////////////////////////////////////////////////////////
/// Deprecated block
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_directedRelation /// @startDocuBlock JSF_general_graph_directedRelation
/// @brief Define a directed relation. /// @brief Define a directed relation.
@ -1410,8 +1417,49 @@ var _undirectedRelation = function (relationName, vertexCollections) {
/// ///
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph_relation
/// @brief Define a directed relation.
///
/// `graph_module._relation(relationName, fromVertexCollections, toVertexCollections)`
///
/// The *relationName* defines the name of this relation and references to the underlying edge collection.
/// The *fromVertexCollections* is an Array of document collections holding the start vertices.
/// The *toVertexCollections* is an Array of document collections holding the target vertices.
/// Relations are only allowed in the direction from any collection in *fromVertexCollections*
/// to any collection in *toVertexCollections*.
///
/// @PARAMS
///
/// @PARAM{relationName, string, required}
/// The name of the edge collection where the edges should be stored.
/// Will be created if it does not yet exist.
///
/// @PARAM{fromVertexCollections, array, required}
/// One or a list of collection names. Source vertices for the edges
/// have to be stored in these collections. Collections will be created if they do not exist.
///
/// @PARAM{toVertexCollections, array, required}
/// One or a list of collection names. Target vertices for the edges
/// have to be stored in these collections. Collections will be created if they do not exist.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphRelationDefinition}
/// var graph_module = require("org/arangodb/general-graph");
/// graph_module._relation("has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]);
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphRelationDefinitionSingle}
/// var graph_module = require("org/arangodb/general-graph");
/// graph_module._relation("has_bought", "Customer", "Product");
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
var _directedRelation = function ( var _relation = function (
relationName, fromVertexCollections, toVertexCollections) { relationName, fromVertexCollections, toVertexCollections) {
var err; var err;
if (arguments.length < 3) { if (arguments.length < 3) {
@ -1499,8 +1547,8 @@ var _listObjects = function() {
/// ///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitions} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitions}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// directed_relation = graph_module._directedRelation("lives_in", "user", "city"); /// directed_relation = graph_module._relation("lives_in", "user", "city");
/// undirected_relation = graph_module._undirectedRelation("knows", "user"); /// undirected_relation = graph_module._relation("knows", "user", "user");
/// edgedefinitions = graph_module._edgeDefinitions(directed_relation, undirected_relation); /// edgedefinitions = graph_module._edgeDefinitions(directed_relation, undirected_relation);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
/// ///
@ -1541,8 +1589,8 @@ var _edgeDefinitions = function () {
/// ///
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitionsExtend} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphEdgeDefinitionsExtend}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// directed_relation = graph_module._directedRelation("lives_in", "user", "city"); /// directed_relation = graph_module._relation("lives_in", "user", "city");
/// undirected_relation = graph_module._undirectedRelation("knows", "user"); /// undirected_relation = graph_module._relation("knows", "user", "user");
/// edgedefinitions = graph_module._edgeDefinitions(directed_relation); /// edgedefinitions = graph_module._edgeDefinitions(directed_relation);
/// edgedefinitions = graph_module._extendEdgeDefinitions(undirected_relation); /// edgedefinitions = graph_module._extendEdgeDefinitions(undirected_relation);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
@ -1604,7 +1652,7 @@ var sortEdgeDefinition = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3}
/// ~ var graph_module = require("org/arangodb/general-graph"); /// ~ var graph_module = require("org/arangodb/general-graph");
/// ~ var graph = graph_module._create("myGraph"); /// ~ var graph = graph_module._create("myGraph");
/// var rel = graph_module._directedRelation("isCustomer", ["shop"], ["customer"]); /// var rel = graph_module._relation("isCustomer", ["shop"], ["customer"]);
/// graph._extendEdgeDefinitions(rel); /// graph._extendEdgeDefinitions(rel);
/// graph; /// graph;
/// ~ graph_module._drop("myGraph", true); /// ~ graph_module._drop("myGraph", true);
@ -1653,7 +1701,7 @@ var sortEdgeDefinition = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraph2} /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraph2}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// | graph = graph_module._create("myGraph", /// | graph = graph_module._create("myGraph",
/// [graph_module._undirectedRelation("myRelation", ["male", "female"])], ["sessions"]); /// [graph_module._relation("myRelation", ["male", "female"])], ["sessions"]);
/// ~ graph_module._drop("myGraph", true); /// ~ graph_module._drop("myGraph", true);
/// @END_EXAMPLE_ARANGOSH_OUTPUT /// @END_EXAMPLE_ARANGOSH_OUTPUT
/// ///
@ -3899,8 +3947,8 @@ Graph.prototype._diameter = function(options) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__extendEdgeDefinitions} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__extendEdgeDefinitions}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._extendEdgeDefinitions(ed2); /// graph._extendEdgeDefinitions(ed2);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4080,8 +4128,8 @@ var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollectio
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__editEdgeDefinition} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__editEdgeDefinition}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var original = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var original = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var modified = graph_module._directedRelation("myEC1", ["myVC2"], ["myVC3"]); /// var modified = graph_module._relation("myEC1", ["myVC2"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [original]); /// var graph = graph_module._create("myGraph", [original]);
/// graph._editEdgeDefinitions(modified); /// graph._editEdgeDefinitions(modified);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4159,8 +4207,8 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinition} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinition}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1, ed2]); /// var graph = graph_module._create("myGraph", [ed1, ed2]);
/// graph._deleteEdgeDefinition("myEC1"); /// graph._deleteEdgeDefinition("myEC1");
/// db._collection("myEC1"); /// db._collection("myEC1");
@ -4172,8 +4220,8 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinitionWithDrop} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinitionWithDrop}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph_module._directedRelation("myEC2", ["myVC1"], ["myVC3"]); /// var ed2 = graph_module._relation("myEC2", ["myVC1"], ["myVC3"]);
/// var graph = graph_module._create("myGraph", [ed1, ed2]); /// var graph = graph_module._create("myGraph", [ed1, ed2]);
/// graph._deleteEdgeDefinition("myEC1", true); /// graph._deleteEdgeDefinition("myEC1", true);
/// db._collection("myEC1"); /// db._collection("myEC1");
@ -4257,7 +4305,7 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollection)
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__addVertexCollection} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__addVertexCollection}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// ~ var blub = graph_module._drop("myGraph", true); /// ~ var blub = graph_module._drop("myGraph", true);
@ -4317,7 +4365,7 @@ Graph.prototype._addVertexCollection = function(vertexCollectionName, createColl
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__orphanCollections} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__orphanCollections}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// graph._orphanCollections(); /// graph._orphanCollections();
@ -4356,7 +4404,7 @@ Graph.prototype._orphanCollections = function() {
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__removeVertexCollections} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__removeVertexCollections}
/// var graph_module = require("org/arangodb/general-graph") /// var graph_module = require("org/arangodb/general-graph")
/// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);} /// ~ if (graph_module._exists("myGraph")){var blub = graph_module._drop("myGraph", true);}
/// var ed1 = graph_module._directedRelation("myEC1", ["myVC1"], ["myVC2"]); /// var ed1 = graph_module._relation("myEC1", ["myVC1"], ["myVC2"]);
/// var graph = graph_module._create("myGraph", [ed1]); /// var graph = graph_module._create("myGraph", [ed1]);
/// graph._addVertexCollection("myVC3", true); /// graph._addVertexCollection("myVC3", true);
/// graph._addVertexCollection("myVC4", true); /// graph._addVertexCollection("myVC4", true);
@ -4421,8 +4469,13 @@ Graph.prototype._PRINT = function(context) {
// --SECTION-- MODULE EXPORTS // --SECTION-- MODULE EXPORTS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/// Deprecated function (announced 2.3)
exports._undirectedRelation = _undirectedRelation; exports._undirectedRelation = _undirectedRelation;
exports._directedRelation = _directedRelation; /// Deprecated function (announced 2.3)
exports._directedRelation = function () {
return _relation.apply(this, arguments);
} ;
exports._relation = _relation;
exports._graph = _graph; exports._graph = _graph;
exports._edgeDefinitions = _edgeDefinitions; exports._edgeDefinitions = _edgeDefinitions;
exports._extendEdgeDefinitions = _extendEdgeDefinitions; exports._extendEdgeDefinitions = _extendEdgeDefinitions;
@ -4451,9 +4504,9 @@ exports._listObjects = _listObjects;
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example1} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example1}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// var edgeDefinitions = graph_module._edgeDefinitions(); /// var edgeDefinitions = graph_module._edgeDefinitions();
/// graph_module._extendEdgeDefinitions(edgeDefinitions, graph_module._undirectedRelation("friend_of", ["Customer"])); /// graph_module._extendEdgeDefinitions(edgeDefinitions, graph_module._relation("friend_of", "Customer", "Customer"));
/// | graph_module._extendEdgeDefinitions( /// | graph_module._extendEdgeDefinitions(
/// | edgeDefinitions, graph_module._directedRelation( /// | edgeDefinitions, graph_module._relation(
/// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"])); /// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]));
/// graph_module._create("myStore", edgeDefinitions); /// graph_module._create("myStore", edgeDefinitions);
/// ~ graph_module._drop("myStore"); /// ~ graph_module._drop("myStore");
@ -4468,7 +4521,7 @@ exports._listObjects = _listObjects;
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example2} /// @EXAMPLE_ARANGOSH_OUTPUT{general_graph_create_graph_example2}
/// var graph_module = require("org/arangodb/general-graph"); /// var graph_module = require("org/arangodb/general-graph");
/// | var edgeDefinitions = graph_module._edgeDefinitions( /// | var edgeDefinitions = graph_module._edgeDefinitions(
/// | graph_module._undirectedRelation("friend_of", ["Customer"]), graph_module._directedRelation( /// | graph_module._relation("friend_of", ["Customer"]), graph_module._relation(
/// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"])); /// "has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]));
/// graph_module._create("myStore", edgeDefinitions); /// graph_module._create("myStore", edgeDefinitions);
/// ~ graph_module._drop("myStore"); /// ~ graph_module._drop("myStore");

View File

@ -33,7 +33,7 @@
var createTraversalExample = function() { var createTraversalExample = function() {
var g = Graph._create("knows_graph", var g = Graph._create("knows_graph",
[Graph._undirectedRelation("knows", "persons")] [Graph._relation("knows", "persons", "persons")]
); );
var a = g.persons.save({name: "Alice", _key: "alice"})._id; var a = g.persons.save({name: "Alice", _key: "alice"})._id;
var b = g.persons.save({name: "Bob", _key: "bob"})._id; var b = g.persons.save({name: "Bob", _key: "bob"})._id;
@ -50,7 +50,7 @@
var createSocialGraph = function() { var createSocialGraph = function() {
var edgeDefinition = []; var edgeDefinition = [];
edgeDefinition.push(Graph._undirectedRelation("relation", ["female", "male"])); edgeDefinition.push(Graph._relation("relation", ["female", "male"], ["female", "male"]));
var g = Graph._create("social", edgeDefinition); var g = Graph._create("social", edgeDefinition);
var a = g.female.save({name: "Alice", _key: "alice"}); var a = g.female.save({name: "Alice", _key: "alice"});
var b = g.male.save({name: "Bob", _key: "bob"}); var b = g.male.save({name: "Bob", _key: "bob"});
@ -65,13 +65,13 @@
var createRoutePlannerGraph = function() { var createRoutePlannerGraph = function() {
var edgeDefinition = []; var edgeDefinition = [];
edgeDefinition.push(Graph._directedRelation( edgeDefinition.push(Graph._relation(
"germanHighway", ["germanCity"], ["germanCity"]) "germanHighway", ["germanCity"], ["germanCity"])
); );
edgeDefinition.push( edgeDefinition.push(
Graph._directedRelation("frenchHighway", ["frenchCity"], ["frenchCity"]) Graph._relation("frenchHighway", ["frenchCity"], ["frenchCity"])
); );
edgeDefinition.push(Graph._directedRelation( edgeDefinition.push(Graph._relation(
"internationalHighway", ["frenchCity", "germanCity"], ["frenchCity", "germanCity"]) "internationalHighway", ["frenchCity", "germanCity"], ["frenchCity", "germanCity"])
); );
var g = Graph._create("routeplanner", edgeDefinition); var g = Graph._create("routeplanner", edgeDefinition);

View File

@ -420,7 +420,7 @@ function DatabaseSuite () {
internal.db._useDatabase("UnitTestsDatabase0"); internal.db._useDatabase("UnitTestsDatabase0");
assertEqual("UnitTestsDatabase0", internal.db._name()); assertEqual("UnitTestsDatabase0", internal.db._name());
var c1 = internal.db._create("test1"); var c1 = internal.db._create("test1");
assertEqual([ "test1" ], getCollections()); assertNotEqual(-1, getCollections().indexOf("test1"));
c1.save({ "_key": "foo" }); c1.save({ "_key": "foo" });
assertEqual(1, internal.db._collection("test1").count()); assertEqual(1, internal.db._collection("test1").count());
assertEqual(1, c1.count()); assertEqual(1, c1.count());
@ -429,7 +429,7 @@ function DatabaseSuite () {
internal.db._useDatabase("UNITTESTSDATABASE0"); internal.db._useDatabase("UNITTESTSDATABASE0");
assertEqual("UNITTESTSDATABASE0", internal.db._name()); assertEqual("UNITTESTSDATABASE0", internal.db._name());
var c2 = internal.db._create("test1"); var c2 = internal.db._create("test1");
assertEqual([ "test1" ], getCollections()); assertNotEqual(-1, getCollections().indexOf("test1"));
c2.save({ "_key": "foo" }); c2.save({ "_key": "foo" });
c2.save({ "_key": "bar" }); c2.save({ "_key": "bar" });
c2.save({ "_key": "baz" }); c2.save({ "_key": "baz" });

View File

@ -53,8 +53,8 @@ function GeneralGraphCreationSuite() {
var vn4 = "UnitTestVerticies4"; var vn4 = "UnitTestVerticies4";
var gn = "UnitTestGraph"; var gn = "UnitTestGraph";
var edgeDef = graph._edgeDefinitions( var edgeDef = graph._edgeDefinitions(
graph._undirectedRelation(rn, vn1), graph._relation(rn, [vn1], [vn1]),
graph._directedRelation(rn1, graph._relation(rn1,
[vn1, vn2], [vn3, vn4] [vn1, vn2], [vn3, vn4]
) )
); );
@ -110,7 +110,7 @@ function GeneralGraphCreationSuite() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
test_undirectedRelation : function () { test_undirectedRelation : function () {
var r = graph._undirectedRelation(rn, [vn1, vn2]); var r = graph._relation(rn, [vn1, vn2], [vn1, vn2]);
assertEqual(r, { assertEqual(r, {
collection: rn, collection: rn,
@ -121,7 +121,7 @@ function GeneralGraphCreationSuite() {
}, },
test_undirectedRelationWithSingleCollection : function () { test_undirectedRelationWithSingleCollection : function () {
var r = graph._undirectedRelation(rn, vn1); var r = graph._relation(rn, vn1, vn1);
assertEqual(r, { assertEqual(r, {
collection: rn, collection: rn,
@ -133,33 +133,21 @@ function GeneralGraphCreationSuite() {
test_undirectedRelationWithMissingName : function () { test_undirectedRelationWithMissingName : function () {
try { try {
graph._undirectedRelation("", [vn1, vn2]); graph._relation("", [vn1, vn2], [vn1, vn2]);
fail(); fail();
} }
catch (err) { catch (err) {
assertEqual(err.errorMessage, "Invalid parameter type. arg1 must not be empty"); assertEqual(err.errorMessage, "Invalid parameter type. arg1 must be non empty string");
} }
}, },
test_undirectedRelationWithTooFewArgs : function () { test_relationWithTooFewArgs : function () {
try { try {
graph._undirectedRelation([vn1, vn2]); graph._relation([vn1, vn2]);
fail(); fail();
} }
catch (err) { catch (err) {
assertEqual(err.errorMessage, "Invalid number of arguments. Expected: 2"); assertEqual(err.errorMessage, "Invalid number of arguments. Expected: 3");
}
},
test_undirectedRelationWithInvalidSecondArg : function () {
try {
var param = {};
param[vn1] = vn2;
graph._undirectedRelation(rn, param);
fail();
}
catch (err) {
assertEqual(err.errorMessage, "Invalid parameter type. arg2 must not be empty");
} }
}, },
@ -167,7 +155,7 @@ function GeneralGraphCreationSuite() {
var g = graph._create( var g = graph._create(
gn, gn,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(rn1, [vn2, vn1], [vn4, vn3]) graph._relation(rn1, [vn2, vn1], [vn4, vn3])
) )
); );
@ -178,7 +166,7 @@ function GeneralGraphCreationSuite() {
}, },
test_directedRelation : function () { test_directedRelation : function () {
var r = graph._directedRelation(rn, var r = graph._relation(rn,
[vn1, vn2], [vn3, vn4]); [vn1, vn2], [vn3, vn4]);
assertEqual(r, { assertEqual(r, {
@ -191,7 +179,7 @@ function GeneralGraphCreationSuite() {
test_directedRelationWithMissingName : function () { test_directedRelationWithMissingName : function () {
try { try {
graph._directedRelation("", graph._relation("",
[vn1, vn2], [vn3, vn4]); [vn1, vn2], [vn3, vn4]);
fail(); fail();
} }
@ -202,7 +190,7 @@ function GeneralGraphCreationSuite() {
test_directedRelationWithTooFewArgs : function () { test_directedRelationWithTooFewArgs : function () {
try { try {
graph._directedRelation([vn1, vn2], [vn3, vn4]); graph._relation([vn1, vn2], [vn3, vn4]);
fail(); fail();
} }
catch (err) { catch (err) {
@ -210,11 +198,11 @@ function GeneralGraphCreationSuite() {
} }
}, },
test_directedRelationWithInvalidSecondArg : function () { test_relationWithInvalidSecondArg : function () {
try { try {
var param = {}; var param = {};
param[vn1] = vn2; param[vn1] = vn2;
graph._directedRelation(rn, param, vn3); graph._relation(rn, param, vn3);
fail(); fail();
} }
catch (err) { catch (err) {
@ -224,11 +212,11 @@ function GeneralGraphCreationSuite() {
}, },
test_directedRelationWithInvalidThirdArg : function () { test_relationWithInvalidThirdArg : function () {
try { try {
var param = {}; var param = {};
param[vn1] = vn2; param[vn1] = vn2;
graph._directedRelation(rn, vn3, param); graph._relation(rn, vn3, param);
fail(); fail();
} }
catch (err) { catch (err) {
@ -243,8 +231,8 @@ function GeneralGraphCreationSuite() {
//with args //with args
assertEqual(graph._edgeDefinitions( assertEqual(graph._edgeDefinitions(
graph._undirectedRelation(rn, vn1), graph._relation(rn, vn1, vn1),
graph._directedRelation(rn1, graph._relation(rn1,
[vn1, vn2], [vn3, vn4]) [vn1, vn2], [vn3, vn4])
), [ ), [
{ {
@ -268,12 +256,12 @@ function GeneralGraphCreationSuite() {
//with args //with args
var ed =graph._edgeDefinitions( var ed =graph._edgeDefinitions(
graph._undirectedRelation("relationName", "vertexC1"), graph._relation("relationName", "vertexC1", "vertexC1"),
graph._directedRelation("relationName", graph._relation("relationName",
["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"]) ["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"])
); );
graph._extendEdgeDefinitions(ed, graph._extendEdgeDefinitions(ed,
graph._undirectedRelation("relationName", "vertexC1") graph._relation("relationName", "vertexC1", "vertexC1")
); );
assertEqual(ed, [ assertEqual(ed, [
{ {
@ -303,8 +291,8 @@ function GeneralGraphCreationSuite() {
var a = graph._create( var a = graph._create(
gn, gn,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(rn, vn1), graph._relation(rn, vn1, vn1),
graph._directedRelation(rn1, [vn1, vn2], [vn3, vn4]) graph._relation(rn1, [vn1, vn2], [vn3, vn4])
) )
); );
assertTrue(a.__vertexCollections.hasOwnProperty(vn1)); assertTrue(a.__vertexCollections.hasOwnProperty(vn1));
@ -356,8 +344,8 @@ function GeneralGraphCreationSuite() {
graph._create( graph._create(
"", "",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation("relationName", "vertexC1"), graph._relation("relationName", "vertexC1", "vertexC1"),
graph._directedRelation("relationName2", graph._relation("relationName2",
["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"] ["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"]
) )
) )
@ -433,7 +421,7 @@ function GeneralGraphCreationSuite() {
if(graph._exists(gn)) { if(graph._exists(gn)) {
graph._drop(gn, true); graph._drop(gn, true);
} }
var edgeDef2 = [graph._directedRelation(rn, vn1, vn2)]; var edgeDef2 = [graph._relation(rn, vn1, vn2)];
var g = graph._create(gn, edgeDef2); var g = graph._create(gn, edgeDef2);
var v1 = g[vn1].save({_key: "1"})._id; var v1 = g[vn1].save({_key: "1"})._id;
var v2 = g[vn2].save({_key: "2"})._id; var v2 = g[vn2].save({_key: "2"})._id;
@ -471,7 +459,7 @@ function GeneralGraphCreationSuite() {
test_deleteEdgeDefinitionFromExistingGraph1: function() { test_deleteEdgeDefinitionFromExistingGraph1: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
g1 = graph._create(gN1, [dr1]); g1 = graph._create(gN1, [dr1]);
try { try {
@ -487,9 +475,9 @@ function GeneralGraphCreationSuite() {
test_deleteEdgeDefinitionFromExistingGraph2: function() { test_deleteEdgeDefinitionFromExistingGraph2: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc3], [vc4, vc5]), dr2 = graph._relation(ec2, [vc3], [vc4, vc5]),
dr3 = graph._directedRelation(ec3, [vc4], [vc5]), dr3 = graph._relation(ec3, [vc4], [vc5]),
g1 = graph._create(gN1, [dr1, dr2, dr3]); g1 = graph._create(gN1, [dr1, dr2, dr3]);
assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions); assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions);
@ -506,9 +494,9 @@ function GeneralGraphCreationSuite() {
test_deleteEdgeDefinitionFromExistingGraphAndDropIt: function() { test_deleteEdgeDefinitionFromExistingGraphAndDropIt: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc3], [vc4, vc5]), dr2 = graph._relation(ec2, [vc3], [vc4, vc5]),
dr3 = graph._directedRelation(ec3, [vc4], [vc5]), dr3 = graph._relation(ec3, [vc4], [vc5]),
g1 = graph._create(gN1, [dr1, dr2, dr3]); g1 = graph._create(gN1, [dr1, dr2, dr3]);
assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions); assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions);
@ -530,8 +518,8 @@ function GeneralGraphCreationSuite() {
} catch(ignore) { } catch(ignore) {
} }
var dr1 = graph._directedRelation(ec1, [vc1], [vc2]), var dr1 = graph._relation(ec1, [vc1], [vc2]),
dr2 = graph._directedRelation(ec1, [vc2], [vc3]), dr2 = graph._relation(ec1, [vc2], [vc3]),
g1 = graph._create(gN1, [dr1]); g1 = graph._create(gN1, [dr1]);
try { try {
@ -552,9 +540,9 @@ function GeneralGraphCreationSuite() {
test_extendEdgeDefinitionFromExistingGraph2: function() { test_extendEdgeDefinitionFromExistingGraph2: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc3], [vc4, vc5]), dr2 = graph._relation(ec2, [vc3], [vc4, vc5]),
dr2a = graph._directedRelation(ec2, [vc3], [vc4]), dr2a = graph._relation(ec2, [vc3], [vc4]),
g1 = graph._create(gN1, [dr1]), g1 = graph._create(gN1, [dr1]),
g2 = graph._create(gN2, [dr2]); g2 = graph._create(gN2, [dr2]);
@ -588,9 +576,9 @@ function GeneralGraphCreationSuite() {
} catch(ignore) { } catch(ignore) {
} }
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc3], [vc4, vc5]), dr2 = graph._relation(ec2, [vc3], [vc4, vc5]),
dr3 = graph._directedRelation(ec3, [vc3], [vc4]), dr3 = graph._relation(ec3, [vc3], [vc4]),
g1 = graph._create(gN1, [dr1]), g1 = graph._create(gN1, [dr1]),
g2 = graph._create(gN2, [dr2]); g2 = graph._create(gN2, [dr2]);
@ -615,8 +603,8 @@ function GeneralGraphCreationSuite() {
} catch(ignore) { } catch(ignore) {
} }
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc4, vc3, vc1, vc2], [vc4, vc3, vc1, vc2]), dr2 = graph._relation(ec2, [vc4, vc3, vc1, vc2], [vc4, vc3, vc1, vc2]),
g1 = graph._create(gN1, [dr1]); g1 = graph._create(gN1, [dr1]);
g1._extendEdgeDefinitions(dr2); g1._extendEdgeDefinitions(dr2);
@ -629,8 +617,8 @@ function GeneralGraphCreationSuite() {
}, },
test_editEdgeDefinitionFromExistingGraph1: function() { test_editEdgeDefinitionFromExistingGraph1: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec2, [vc3], [vc4, vc5]), dr2 = graph._relation(ec2, [vc3], [vc4, vc5]),
g1 = graph._create(gN1, [dr1]); g1 = graph._create(gN1, [dr1]);
try { try {
@ -646,9 +634,9 @@ function GeneralGraphCreationSuite() {
test_editEdgeDefinitionFromExistingGraph2: function() { test_editEdgeDefinitionFromExistingGraph2: function() {
var dr1 = graph._directedRelation(ec1, [vc1, vc2], [vc3, vc4]), var dr1 = graph._relation(ec1, [vc1, vc2], [vc3, vc4]),
dr2 = graph._directedRelation(ec2, [vc1], [vc4]), dr2 = graph._relation(ec2, [vc1], [vc4]),
dr3 = graph._directedRelation(ec1, [vc5], [vc5]), dr3 = graph._relation(ec1, [vc5], [vc5]),
g1 = graph._create(gN1, [dr1, dr2]), g1 = graph._create(gN1, [dr1, dr2]),
g2 = graph._create(gN2, [dr1]); g2 = graph._create(gN2, [dr1]);
@ -663,9 +651,9 @@ function GeneralGraphCreationSuite() {
test_editEdgeDefinitionFromExistingGraph3: function() { test_editEdgeDefinitionFromExistingGraph3: function() {
var dr1 = graph._directedRelation(ec1, [vc1], [vc1, vc2]), var dr1 = graph._relation(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelation(ec1, [vc3], [vc4, vc5]), dr2 = graph._relation(ec1, [vc3], [vc4, vc5]),
dr3 = graph._directedRelation(ec2, [vc2], [vc2, vc3]), dr3 = graph._relation(ec2, [vc2], [vc2, vc3]),
g1 = graph._create(gN1, [dr1, dr3]), g1 = graph._create(gN1, [dr1, dr3]),
g2 = graph._create(gN2, [dr1]); g2 = graph._create(gN2, [dr1]);
@ -719,10 +707,10 @@ function GeneralGraphAQLQueriesSuite() {
var createInclExcl = function() { var createInclExcl = function() {
dropInclExcl(); dropInclExcl();
var inc = graph._directedRelation( var inc = graph._relation(
included, [v1], [v1, v2] included, [v1], [v1, v2]
); );
var exc = graph._directedRelation( var exc = graph._relation(
excluded, [v1], [v3] excluded, [v1], [v3]
); );
var g = graph._create(graphName, [inc, exc]); var g = graph._create(graphName, [inc, exc]);
@ -998,8 +986,8 @@ function ChainedFluentAQLResultsSuite() {
var g; var g;
var edgeDef = []; var edgeDef = [];
edgeDef.push(graph._undirectedRelation(isFriend, user)); edgeDef.push(graph._relation(isFriend, user, user));
edgeDef.push(graph._directedRelation(hasBought, user, product)); edgeDef.push(graph._relation(hasBought, user, product));
var findBoughts = function(result, list) { var findBoughts = function(result, list) {
@ -1475,7 +1463,7 @@ function ChainedFluentAQLResultsSuite() {
} catch (ignore) { } catch (ignore) {
} }
var g2 = graph._create(emptyGN, [ var g2 = graph._create(emptyGN, [
graph._undirectedRelation(emptyEdges, emptyVertices) graph._relation(emptyEdges, emptyVertices, emptyVertices)
]); ]);
g2[emptyVertices].save({_key: "highlander"}); g2[emptyVertices].save({_key: "highlander"});
var res = g2._vertices(emptyVertices + "/highlander").edges().restrict(emptyEdges).toArray(); var res = g2._vertices(emptyVertices + "/highlander").edges().restrict(emptyEdges).toArray();
@ -1894,8 +1882,8 @@ function EdgesAndVerticesSuite() {
g = graph._create( g = graph._create(
unitTestGraphName, unitTestGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(ec1, vc1), graph._relation(ec1, vc1, vc1),
graph._directedRelation(ec2, graph._relation(ec2,
[vc1, vc2], [vc3, vc4] [vc1, vc2], [vc3, vc4]
) )
) )
@ -1913,7 +1901,7 @@ function EdgesAndVerticesSuite() {
graph._create( graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(myEdgeColName, myVertexColName) graph._relation(myEdgeColName, myVertexColName, myVertexColName)
) )
); );
graph._drop(myGraphName, true); graph._drop(myGraphName, true);
@ -1929,7 +1917,7 @@ function EdgesAndVerticesSuite() {
graph._create( graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(myEdgeColName, myVertexColName) graph._relation(myEdgeColName, myVertexColName, myVertexColName)
) )
); );
graph._drop(myGraphName); graph._drop(myGraphName);
@ -1943,7 +1931,7 @@ function EdgesAndVerticesSuite() {
graph._create( graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(ec1, vc1) graph._relation(ec1, vc1, vc1)
) )
); );
assertTrue(graph._exists(myGraphName)); assertTrue(graph._exists(myGraphName));
@ -1959,7 +1947,7 @@ function EdgesAndVerticesSuite() {
graph._create( graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(ec1, vc2) graph._relation(ec1, vc2, vc2)
) )
); );
} catch (e) { } catch (e) {
@ -1984,8 +1972,8 @@ function EdgesAndVerticesSuite() {
graph._create( graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(myED, myVD1), graph._relation(myED, myVD1, myVD1),
graph._undirectedRelation(myED, myVD2) graph._relation(myED, myVD2, myVD2)
) )
); );
} catch (e) { } catch (e) {
@ -2185,7 +2173,7 @@ function EdgesAndVerticesSuite() {
var g2 = graph._create( var g2 = graph._create(
myGraphName, myGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(myEC02, graph._relation(myEC02,
[ec1], [myVC01] [ec1], [myVC01]
) )
) )
@ -2236,18 +2224,18 @@ function EdgesAndVerticesSuite() {
} catch (ignore) { } catch (ignore) {
} }
db._createEdgeCollection(eC1) db._createEdgeCollection(eC1);
db._createEdgeCollection(eC2) db._createEdgeCollection(eC2);
db._createEdgeCollection(eC3) db._createEdgeCollection(eC3);
db._createEdgeCollection(eC4) db._createEdgeCollection(eC4);
db._create(vC1) db._create(vC1);
db._create(vC2) db._create(vC2);
db._create(vC3) db._create(vC3);
db._create(vC4) db._create(vC4);
var vertex1 = db[vC1].save({}); var vertex1 = db[vC1].save({});
var vertexId1 = vertex1._id; vertexId1 = vertex1._id;
var vertex2 = db[vC1].save({}); var vertex2 = db[vC1].save({});
var vertexId2 = vertex2._id; vertexId2 = vertex2._id;
var vertex3 = db[vC1].save({}); var vertex3 = db[vC1].save({});
var vertexId3 = vertex3._id; var vertexId3 = vertex3._id;
var vertex4 = db[vC1].save({}); var vertex4 = db[vC1].save({});
@ -2260,25 +2248,25 @@ function EdgesAndVerticesSuite() {
var g1 = graph._create( var g1 = graph._create(
gN1, gN1,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(eC1, [eC4], [vC1]) graph._relation(eC1, [eC4], [vC1])
) )
); );
var g2 = graph._create( var g2 = graph._create(
gN2, gN2,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(eC2, [eC1], [vC2]) graph._relation(eC2, [eC1], [vC2])
) )
); );
var g3 = graph._create( var g3 = graph._create(
gN3, gN3,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(eC3, [eC2], [vC3]) graph._relation(eC3, [eC2], [vC3])
) )
); );
var g4 = graph._create( var g4 = graph._create(
gN4, gN4,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(eC4, [eC3], [vC4]) graph._relation(eC4, [eC3], [vC4])
) )
); );
@ -2390,7 +2378,7 @@ function GeneralGraphCommonNeighborsSuite() {
testGraph = graph._create( testGraph = graph._create(
"bla3", "bla3",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation(eColName, graph._relation(eColName,
[v1ColName, v2ColName], [v1ColName, v2ColName],
[v1ColName, v2ColName] [v1ColName, v2ColName]
) )
@ -2576,7 +2564,7 @@ function OrphanCollectionSuite() {
g1 = graph._create( g1 = graph._create(
gN1, gN1,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation( graph._relation(
eC1, [vC1], [vC1, vC2] eC1, [vC1], [vC1, vC2]
) )
) )
@ -2584,7 +2572,7 @@ function OrphanCollectionSuite() {
g2 = graph._create( g2 = graph._create(
gN2, gN2,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation( graph._relation(
eC2, [vC3], [vC1] eC2, [vC3], [vC1]
) )
) )
@ -2791,8 +2779,8 @@ function MeasurementsSuite() {
g = graph._create( g = graph._create(
unitTestGraphName, unitTestGraphName,
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(ec1, vc1), graph._relation(ec1, vc1, vc1),
graph._directedRelation(ec2, graph._relation(ec2,
[vc1, vc2], [vc3, vc4] [vc1, vc2], [vc3, vc4]
) )
) )

View File

@ -1923,8 +1923,8 @@ function GeneralGraphTraversalSuite () {
cleanUp(); cleanUp();
var edgeDef = []; var edgeDef = [];
edgeDef.push(generalGraph._directedRelation(enDir, vnA, vnBDH)); edgeDef.push(generalGraph._relation(enDir, vnA, vnBDH));
edgeDef.push(generalGraph._undirectedRelation(enUndir, [vnBDH, vnCEFGI])); edgeDef.push(generalGraph._relation(enUndir, [vnBDH, vnCEFGI], [vnBDH, vnCEFGI]));
g = generalGraph._create(gn, edgeDef); g = generalGraph._create(gn, edgeDef);
saveVertex(vnA, "A"); saveVertex(vnA, "A");

View File

@ -198,7 +198,7 @@ function extendContext (context, app, root) {
} }
context.collectionName = function (name) { context.collectionName = function (name) {
var replaced = (cp + name.replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '')).substr(0, 64); var replaced = ((cp + name).replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '')).substr(0, 64);
if (replaced.length === 0) { if (replaced.length === 0) {
throw new Error("Cannot derive collection name from '" + name + "'"); throw new Error("Cannot derive collection name from '" + name + "'");

View File

@ -40,6 +40,15 @@ var assertQueryError = helper.assertQueryError;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryGeneralEdgesTestSuite() { function ahuacatlQueryGeneralEdgesTestSuite() {
var v1 = "UnitTestsAhuacatlVertex1";
var v2 = "UnitTestsAhuacatlVertex2";
var v3 = "UnitTestsAhuacatlVertex3";
var v4 = "UnitTestsAhuacatlVertex4";
var e1 = "UnitTestsAhuacatlEdge1";
var e2 = "UnitTestsAhuacatlEdge2";
var or = "UnitTestsAhuacatlOrphan";
return { return {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -47,21 +56,21 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
setUp: function () { setUp: function () {
db._drop("UnitTestsAhuacatlVertex1"); db._drop(v1);
db._drop("UnitTestsAhuacatlVertex2"); db._drop(v2);
db._drop("UnitTestsAhuacatlVertex3"); db._drop(v3);
db._drop("UnitTestsAhuacatlVertex4"); db._drop(v4);
db._drop("UnitTestsAhuacatlEdge1"); db._drop(e1);
db._drop("UnitTestsAhuacatlEdge2"); db._drop(e2);
db._drop("UnitTestsAhuacatlOrphan"); db._drop(or);
var vertex1 = db._create("UnitTestsAhuacatlVertex1"); var vertex1 = db._create(v1);
var vertex2 = db._create("UnitTestsAhuacatlVertex2"); var vertex2 = db._create(v2);
var vertex3 = db._create("UnitTestsAhuacatlVertex3"); var vertex3 = db._create(v3);
var vertex4 = db._create("UnitTestsAhuacatlVertex4"); var vertex4 = db._create(v4);
var edge1 = db._createEdgeCollection("UnitTestsAhuacatlEdge1"); var edge1 = db._createEdgeCollection(e1);
var edge2 = db._createEdgeCollection("UnitTestsAhuacatlEdge2"); var edge2 = db._createEdgeCollection(e2);
var oprhan = db._create("UnitTestsAhuacatlOrphan"); var oprhan = db._create(or);
vertex1.save({ _key: "v1", hugo: true}); vertex1.save({ _key: "v1", hugo: true});
vertex1.save({ _key: "v2", hugo: true}); vertex1.save({ _key: "v2", hugo: true});
@ -77,14 +86,14 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] }); collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] });
} }
makeEdge("UnitTestsAhuacatlVertex1/v1", "UnitTestsAhuacatlVertex1/v2", edge1); makeEdge(v1 + "/v1", v1 + "/v2", edge1);
makeEdge("UnitTestsAhuacatlVertex1/v2", "UnitTestsAhuacatlVertex1/v1", edge1); makeEdge(v1 + "/v2", v1 + "/v1", edge1);
makeEdge("UnitTestsAhuacatlVertex1/v1", "UnitTestsAhuacatlVertex3/v5", edge2); makeEdge(v1 + "/v1", v3 + "/v5", edge2);
makeEdge("UnitTestsAhuacatlVertex1/v2", "UnitTestsAhuacatlVertex3/v5", edge2); makeEdge(v1 + "/v2", v3 + "/v5", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v3", "UnitTestsAhuacatlVertex3/v6", edge2); makeEdge(v2 + "/v3", v3 + "/v6", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v4", "UnitTestsAhuacatlVertex4/v7", edge2); makeEdge(v2 + "/v4", v4 + "/v7", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v3", "UnitTestsAhuacatlVertex3/v5", edge2); makeEdge(v2 + "/v3", v3 + "/v5", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v3", "UnitTestsAhuacatlVertex4/v8", edge2); makeEdge(v2 + "/v3", v4 + "/v8", edge2);
try { try {
db._collection("_graphs").remove("_graphs/bla3"); db._collection("_graphs").remove("_graphs/bla3");
@ -93,13 +102,13 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
graph._create( graph._create(
"bla3", "bla3",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"), graph._relation(e1, v1, v1),
graph._directedRelation("UnitTestsAhuacatlEdge2", graph._relation(e2,
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"], [v1, v2],
["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"] [v3, v4]
) )
), ),
["UnitTestsAhuacatlOrphan"] [or]
); );
}, },
@ -108,13 +117,13 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
tearDown: function () { tearDown: function () {
db._drop("UnitTestsAhuacatlVertex1"); db._drop(v1);
db._drop("UnitTestsAhuacatlVertex2"); db._drop(v2);
db._drop("UnitTestsAhuacatlVertex3"); db._drop(v3);
db._drop("UnitTestsAhuacatlVertex4"); db._drop(v4);
db._drop("UnitTestsAhuacatlEdge1"); db._drop(e1);
db._drop("UnitTestsAhuacatlEdge2"); db._drop(e2);
db._drop("UnitTestsAhuacatlOrphan"); db._drop(or);
db._collection("_graphs").remove("_graphs/bla3"); db._collection("_graphs").remove("_graphs/bla3");
}, },
@ -125,8 +134,8 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
testEdgesAny: function () { testEdgesAny: function () {
var actual; var actual;
actual = getRawQueryResults("FOR e IN GRAPH_VERTICES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'any'}) RETURN e"); actual = getRawQueryResults("FOR e IN GRAPH_VERTICES('bla3', '" + v1 + "/v1', {direction : 'any'}) RETURN e");
assertEqual(actual[0]._id, 'UnitTestsAhuacatlVertex1/v1'); assertEqual(actual[0]._id, v1 + '/v1');
actual = getRawQueryResults("FOR e IN GRAPH_VERTICES('bla3', {}, {direction : 'any', vertexCollectionRestriction : 'UnitTestsAhuacatlOrphan'}) RETURN e"); actual = getRawQueryResults("FOR e IN GRAPH_VERTICES('bla3', {}, {direction : 'any', vertexCollectionRestriction : 'UnitTestsAhuacatlOrphan'}) RETURN e");
assertEqual(actual[0]._id, 'UnitTestsAhuacatlOrphan/orphan'); assertEqual(actual[0]._id, 'UnitTestsAhuacatlOrphan/orphan');
@ -309,7 +318,7 @@ function ahuacatlQueryGeneralCommonTestSuite() {
graph._create( graph._create(
"bla3", "bla3",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._directedRelation("UnitTestsAhuacatlEdge1", graph._relation("UnitTestsAhuacatlEdge1",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"], ["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"] ["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"]
) )
@ -496,8 +505,8 @@ function ahuacatlQueryGeneralPathsTestSuite() {
var g = graph._create( var g = graph._create(
"bla3", "bla3",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"), graph._relation("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex1"),
graph._directedRelation("UnitTestsAhuacatlEdge2", graph._relation("UnitTestsAhuacatlEdge2",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"], ["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"] ["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"]
) )
@ -726,8 +735,8 @@ function ahuacatlQueryGeneralTraversalTestSuite() {
var g = graph._create( var g = graph._create(
"werKenntWen", "werKenntWen",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(KenntAnderenBerliner, "UnitTests_Berliner"), graph._relation(KenntAnderenBerliner, "UnitTests_Berliner", "UnitTests_Berliner"),
graph._directedRelation(KenntAnderen, graph._relation(KenntAnderen,
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"], ["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"],
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"] ["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"]
) )
@ -1691,8 +1700,8 @@ function ahuacatlQueryGeneralCyclesSuite() {
var g = graph._create( var g = graph._create(
"werKenntWen", "werKenntWen",
graph._edgeDefinitions( graph._edgeDefinitions(
graph._undirectedRelation(KenntAnderenBerliner, "UnitTests_Berliner"), graph._relation(KenntAnderenBerliner, "UnitTests_Berliner", "UnitTests_Berliner"),
graph._directedRelation(KenntAnderen, graph._relation(KenntAnderen,
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"], ["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"],
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"] ["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"]
) )

View File

@ -0,0 +1,294 @@
/*global require, exports, assertTrue, assertEqual, AQL_EXECUTE, AQL_EXPLAIN */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for optimizer rules
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 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 Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var errors = require("internal").errors;
var internal = require("internal");
var errors = internal.errors;
var db = require("org/arangodb").db;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function explainSuite () {
var cn = "UnitTestsAhuacatlExplain";
var c;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
db._drop(cn);
c = db._create(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test bind parameters
////////////////////////////////////////////////////////////////////////////////
testExplainBindMissing : function () {
var actual;
var query = "RETURN @foo";
try {
actual = AQL_EXPLAIN(query);
fail();
}
catch (err) {
assertEqual(err.errorNum, errors.ERROR_QUERY_BIND_PARAMETER_MISSING.code);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test bind parameters
////////////////////////////////////////////////////////////////////////////////
testExplainBindPresent : function () {
var actual;
var query = "RETURN @foo";
actual = AQL_EXPLAIN(query, { foo: "bar" });
assertEqual(3, actual.plan.nodes.length);
assertEqual("SingletonNode", actual.plan.nodes[0].type);
assertEqual("CalculationNode", actual.plan.nodes[1].type);
assertEqual("ReturnNode", actual.plan.nodes[2].type);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test verbosity w/ single plan
////////////////////////////////////////////////////////////////////////////////
testExplainVerbosity : function () {
var actual;
var query = "FOR i IN " + cn + " FOR j IN " + cn + " RETURN i";
// single plan, no options
actual = AQL_EXPLAIN(query);
assertTrue(actual.hasOwnProperty("plan"));
assertFalse(Array.isArray(actual.plan));
assertTrue(actual.plan.hasOwnProperty("nodes"));
assertTrue(Array.isArray(actual.plan.nodes));
assertTrue(actual.plan.hasOwnProperty("rules"));
assertTrue(Array.isArray(actual.plan.rules));
assertFalse(actual.plan.hasOwnProperty("estimatedCost"));
actual.plan.nodes.forEach(function(node) {
assertTrue(node.hasOwnProperty("type"));
assertFalse(node.hasOwnProperty("typeID")); // deactivated if not verbose
assertTrue(node.hasOwnProperty("dependencies"));
assertTrue(Array.isArray(node.dependencies));
assertFalse(node.hasOwnProperty("parents")); // deactivated if not verbose
assertTrue(node.hasOwnProperty("id"));
assertTrue(node.hasOwnProperty("estimatedCost"));
});
// single plan, verbose options
actual = AQL_EXPLAIN(query, { }, { verbosePlans: true });
assertTrue(actual.hasOwnProperty("plan"));
assertFalse(Array.isArray(actual.plan));
assertTrue(actual.plan.hasOwnProperty("nodes"));
assertTrue(Array.isArray(actual.plan.nodes));
assertTrue(actual.plan.hasOwnProperty("rules"));
assertTrue(Array.isArray(actual.plan.rules));
actual.plan.nodes.forEach(function(node) {
assertTrue(node.hasOwnProperty("type"));
assertTrue(node.hasOwnProperty("typeID"));
assertTrue(node.hasOwnProperty("dependencies"));
assertTrue(Array.isArray(node.dependencies));
assertTrue(node.hasOwnProperty("parents"));
assertTrue(Array.isArray(node.parents));
assertTrue(node.hasOwnProperty("id"));
assertTrue(node.hasOwnProperty("estimatedCost"));
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test explain w/ a signle plan vs. all plans
////////////////////////////////////////////////////////////////////////////////
testExplainAllPlansVsSingle : function () {
var actual;
var query = "FOR i IN " + cn + " FOR j IN " + cn + " RETURN i";
// single plan
actual = AQL_EXPLAIN(query, { }, { verbosePlans: true });
assertTrue(actual.hasOwnProperty("plan"));
assertFalse(actual.hasOwnProperty("plans"));
assertFalse(Array.isArray(actual.plan));
assertTrue(actual.plan.hasOwnProperty("nodes"));
assertTrue(Array.isArray(actual.plan.nodes));
actual.plan.nodes.forEach(function(node) {
assertTrue(node.hasOwnProperty("type"));
assertTrue(node.hasOwnProperty("typeID"));
assertTrue(node.hasOwnProperty("dependencies"));
assertTrue(Array.isArray(node.dependencies));
assertTrue(node.hasOwnProperty("parents"));
assertTrue(node.hasOwnProperty("id"));
assertTrue(node.hasOwnProperty("estimatedCost"));
});
assertTrue(actual.plan.hasOwnProperty("rules"));
assertTrue(Array.isArray(actual.plan.rules));
// multiple plans
actual = AQL_EXPLAIN(query, { }, { allPlans: true, verbosePlans: true });
assertFalse(actual.hasOwnProperty("plan"));
assertTrue(actual.hasOwnProperty("plans"));
assertTrue(Array.isArray(actual.plans));
actual.plans.forEach(function (plan) {
assertTrue(plan.hasOwnProperty("nodes"));
assertTrue(Array.isArray(plan.nodes));
plan.nodes.forEach(function(node) {
assertTrue(node.hasOwnProperty("type"));
assertTrue(node.hasOwnProperty("typeID"));
assertTrue(node.hasOwnProperty("dependencies"));
assertTrue(Array.isArray(node.dependencies));
assertTrue(node.hasOwnProperty("parents"));
assertTrue(node.hasOwnProperty("id"));
assertTrue(node.hasOwnProperty("estimatedCost"));
});
assertTrue(plan.hasOwnProperty("rules"));
assertTrue(Array.isArray(plan.rules));
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nodes in plan
////////////////////////////////////////////////////////////////////////////////
testNodes : function () {
var actual;
var query = "FOR i IN " + cn + " FILTER i.value > 1 LET a = i.value / 2 SORT a DESC COLLECT x = a INTO g RETURN x";
actual = AQL_EXPLAIN(query, null, { optimizer: { rules: [ "-all" ] } });
var nodes = actual.plan.nodes, node;
node = nodes[0];
assertEqual("SingletonNode", node.type);
assertEqual([ ], node.dependencies);
assertEqual(1, node.id);
assertEqual(1, node.estimatedCost);
node = nodes[1];
assertEqual("EnumerateCollectionNode", node.type);
assertEqual([ 1 ], node.dependencies);
assertEqual(2, node.id);
assertEqual(0, node.estimatedCost);
assertEqual("_system", node.database);
assertEqual(cn, node.collection);
assertEqual("i", node.outVariable.name);
node = nodes[2];
assertEqual("CalculationNode", node.type);
assertEqual([ 2 ], node.dependencies);
assertEqual(3, node.id);
assertTrue(node.hasOwnProperty("expression"));
assertFalse(node.canThrow);
var out = node.outVariable.name;
node = nodes[3];
assertEqual("FilterNode", node.type);
assertEqual([ 3 ], node.dependencies);
assertEqual(4, node.id);
assertEqual(0, node.estimatedCost);
assertEqual(out, node.inVariable.name);
node = nodes[4];
assertEqual("CalculationNode", node.type);
assertEqual([ 4 ], node.dependencies);
assertEqual(5, node.id);
assertTrue(node.hasOwnProperty("expression"));
assertEqual("a", node.outVariable.name);
assertTrue(node.canThrow);
node = nodes[5];
assertEqual("SortNode", node.type);
assertEqual([ 5 ], node.dependencies);
assertEqual(6, node.id);
assertEqual(1, node.elements.length);
assertEqual("a", node.elements[0].inVariable.name);
assertFalse(node.stable);
node = nodes[6];
assertEqual("SortNode", node.type);
assertEqual([ 6 ], node.dependencies);
assertEqual(7, node.id);
assertEqual(1, node.elements.length);
assertEqual("a", node.elements[0].inVariable.name);
assertTrue(node.stable);
node = nodes[7];
assertEqual("AggregateNode", node.type);
assertEqual([ 7 ], node.dependencies);
assertEqual(8, node.id);
assertEqual(1, node.aggregates.length);
assertEqual("a", node.aggregates[0].inVariable.name);
assertEqual("x", node.aggregates[0].outVariable.name);
assertEqual("g", node.outVariable.name);
node = nodes[8];
assertEqual("ReturnNode", node.type);
assertEqual([ 8 ], node.dependencies);
assertEqual(9, node.id);
assertEqual("x", node.inVariable.name);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(explainSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -0,0 +1,220 @@
/*global _, require, exports, assertTrue, assertEqual, AQL_EXECUTE, AQL_EXPLAIN */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for optimizer rules
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 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 Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var errors = require("internal").errors;
var helper = require("org/arangodb/aql-helper");
var getQueryResults = helper.getQueryResults2;
var assertQueryError = helper.assertQueryError2;
var isEqual = helper.isEqual;
var db = require("org/arangodb").db;
var _ = require("underscore");
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function optimizerRuleTestSuite () {
var ruleName = "interchange-adjacent-enumerations";
// various choices to control the optimizer:
var paramNone = { optimizer: { rules: [ "-all" ] } };
var paramEnabled = { optimizer: { rules: [ "-all", "+" + ruleName ] } };
var paramDisabled = { optimizer: { rules: [ "+all", "-" + ruleName ] } };
var collection = null;
var collectionName = "UnitTestsAhuacatlOptimizer";
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
db._drop(collectionName);
collection = db._create(collectionName);
for (var i = 0; i < 10; ++i) {
collection.save({ value: i });
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
db._drop(collectionName);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test that rule has no effect when explicitly disabled
////////////////////////////////////////////////////////////////////////////////
testRuleDisabled : function () {
var queries = [
"FOR i IN " + collectionName + " FOR j IN " + collectionName + " RETURN 1",
"FOR j IN " + collectionName + " FILTER j.i == 1 FOR i IN " + collectionName + " RETURN j"
];
var opts = _.clone(paramNone);
opts.allPlans = true;
opts.verbosePlans = true;
queries.forEach(function(query) {
var result = AQL_EXPLAIN(query, { }, opts);
result.plans.forEach(function(plan) {
assertEqual([ ], plan.rules);
});
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test that rule has no effect
////////////////////////////////////////////////////////////////////////////////
testRuleNoEffect : function () {
var queries = [
"FOR i IN 1..10 RETURN i",
"FOR i IN " + collectionName + " RETURN i",
"FOR i IN " + collectionName + " FILTER i == 1 FOR j IN " + collectionName + " RETURN i",
"FOR i IN " + collectionName + " LIMIT 1 FOR j IN " + collectionName + " RETURN i",
"FOR i IN " + collectionName + " RETURN (FOR j IN " + collectionName + " RETURN j)"
];
var opts = _.clone(paramEnabled);
opts.allPlans = true;
opts.verbosePlans = true;
queries.forEach(function(query) {
var result = AQL_EXPLAIN(query, { }, opts);
result.plans.forEach(function(plan) {
assertTrue(plan.rules.indexOf(ruleName) === -1, query);
});
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test that rule has an effect
////////////////////////////////////////////////////////////////////////////////
testRuleHasEffect : function () {
var queries = [
[ "FOR i IN " + collectionName + " FOR j IN " + collectionName + " RETURN i", 1 ],
[ "FOR i IN 1..10 FOR j IN " + collectionName + " FOR k IN " + collectionName + " RETURN i", 1 ],
[ "FOR i IN " + collectionName + " FOR j IN " + collectionName + " FOR k IN " + collectionName + " RETURN i", 5 ],
[ "FOR i IN " + collectionName + " FOR j IN " + collectionName + " FOR k IN " + collectionName + " FOR l IN " + collectionName + " RETURN i", 23 ],
[ "FOR x IN (FOR i IN " + collectionName + " FOR j IN " + collectionName + " RETURN i) RETURN x", 1 ],
[ "FOR x IN (FOR i IN " + collectionName + " FOR j IN " + collectionName + " FOR k IN " + collectionName + " RETURN i) RETURN x", 5 ],
[ "FOR x IN (FOR i IN " + collectionName + " FOR j IN " + collectionName + " FOR k IN " + collectionName + " RETURN i) FOR y IN (FOR i IN " + collectionName + " FOR j IN " + collectionName + " RETURN i) RETURN x", 11 ]
];
var opts = _.clone(paramEnabled);
opts.allPlans = true;
opts.verbosePlans = true;
queries.forEach(function(query) {
var withRule = 0;
var withoutRule = 0;
var result = AQL_EXPLAIN(query[0], { }, opts);
result.plans.forEach(function(plan) {
if (plan.rules.indexOf(ruleName) === -1) {
withoutRule++;
}
else {
withRule++;
}
});
// there should still be the original plan
assertEqual(1, withoutRule, query[0]);
// put there should also be permuted plans
assertEqual(query[1], withRule, query[0]);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test results
////////////////////////////////////////////////////////////////////////////////
testResults : function () {
var queries = [
[ "FOR i IN " + collectionName + " FOR j IN " + collectionName + " SORT i.value, j.value FILTER i.value == j.value RETURN i.value", [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ],
[ "FOR j IN " + collectionName + " FOR i IN " + collectionName + " SORT i.value, j.value FILTER i.value == j.value RETURN i.value", [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ],
[ "FOR x IN (FOR i IN " + collectionName + " FOR j IN " + collectionName + " RETURN { i: i.value, j: j.value }) FILTER x.i == x.j SORT x.i RETURN x.i", [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ]
];
var opts = _.clone(paramEnabled);
opts.allPlans = true;
opts.verbosePlans = true;
queries.forEach(function(query) {
var planDisabled = AQL_EXPLAIN(query[0], { }, paramDisabled);
var plansEnabled = AQL_EXPLAIN(query[0], { }, opts);
var resultDisabled = AQL_EXECUTE(query[0], { }, paramDisabled).json;
assertTrue(planDisabled.plan.rules.indexOf(ruleName) === -1, query[0]);
assertEqual(resultDisabled, query[1]);
assertTrue(plansEnabled.plans.length > 1);
// iterate over all plans
var withRule = 0;
plansEnabled.plans.forEach(function(plan) {
var resultEnabled = AQL_EXECUTEJSON(plan).json;
assertTrue(isEqual(resultDisabled, resultEnabled), query[0]);
if (plan.rules.indexOf(ruleName) !== -1) {
withRule++;
}
assertEqual(resultEnabled, query[1]);
});
assertTrue(withRule > 0);
});
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(optimizerRuleTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End: