1
0
Fork 0

inedges, outedges, edges

This commit is contained in:
Jan Steemann 2014-02-18 13:46:09 +01:00
parent 82e9a87684
commit dc8e590bca
6 changed files with 295 additions and 174 deletions

View File

@ -118,6 +118,18 @@ describe ArangoDB do
doc.parsed_response['error'].should eq(true) doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(404) doc.parsed_response['code'].should eq(404)
end end
it "finds the first example, invalid collection" do
cmd = api + "/first-example"
body = "{ \"collection\" : \"NonExistingCollection\", \"example\" : { \"a\" : 1} }"
doc = ArangoDB.log_put("#{prefix}-first-first-example-not-found", cmd, :body => body)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(404)
doc.parsed_response['errorNum'].should eq(1203)
end
end end
################################################################################ ################################################################################

View File

@ -1559,28 +1559,18 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
for (uint32_t i = 0; i < len; ++i) { for (uint32_t i = 0; i < len; ++i) {
TRI_vector_pointer_t edges; TRI_vector_pointer_t edges;
TRI_voc_cid_t cid; TRI_voc_cid_t cid;
TRI_voc_rid_t rid;
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
TRI_vocbase_col_t const* vertexCollection = 0; res = TRI_ParseVertex(resolver, cid, key, vertices->Get(i), true);
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(resolver, vertexCollection, key, rid, vertices->Get(i));
if (! errMsg.IsEmpty()) {
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
key = 0;
}
if (res != TRI_ERROR_NO_ERROR) {
// error is just ignored
continue; continue;
} }
assert(vertexCollection != 0);
cid = vertexCollection->_cid;
edges = TRI_LookupEdgesDocumentCollection((TRI_document_collection_t*) primary, direction, cid, key); edges = TRI_LookupEdgesDocumentCollection((TRI_document_collection_t*) primary, direction, cid, key);
if (key) { if (key != 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key); TRI_FreeString(TRI_CORE_MEM_ZONE, key);
} }
@ -1618,27 +1608,18 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
// argument is a single vertex // argument is a single vertex
else { else {
TRI_vector_pointer_t edges; TRI_vector_pointer_t edges;
TRI_voc_cid_t cid;
TRI_voc_rid_t rid;
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
TRI_voc_cid_t cid;
res = TRI_ParseVertex(resolver, cid, key, argv[0], true);
TRI_vocbase_col_t const* vertexCollection = 0; if (res != TRI_ERROR_NO_ERROR) {
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(resolver, vertexCollection, key, rid, argv[0]); TRI_V8_EXCEPTION(scope, res);
if (! errMsg.IsEmpty()) {
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
return scope.Close(v8::ThrowException(errMsg));
} }
assert(vertexCollection != 0);
cid = vertexCollection->_cid;
edges = TRI_LookupEdgesDocumentCollection((TRI_document_collection_t*) primary, direction, cid, key); edges = TRI_LookupEdgesDocumentCollection((TRI_document_collection_t*) primary, direction, cid, key);
if (key) { if (key != 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key); TRI_FreeString(TRI_CORE_MEM_ZONE, key);
} }
@ -1669,7 +1650,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
trx.finish(res); trx.finish(res);
// ............................................................................. // .............................................................................
// outside a write transaction // outside a read transaction
// ............................................................................. // .............................................................................
if (error) { if (error) {
@ -3077,17 +3058,17 @@ void TRI_InitV8Queries (v8::Handle<v8::Context> context) {
TRI_AddMethodVocbase(rt, "BY_EXAMPLE_HASH", JS_ByExampleHashIndex, true); TRI_AddMethodVocbase(rt, "BY_EXAMPLE_HASH", JS_ByExampleHashIndex, true);
TRI_AddMethodVocbase(rt, "BY_EXAMPLE_SKIPLIST", JS_ByExampleSkiplist, true); TRI_AddMethodVocbase(rt, "BY_EXAMPLE_SKIPLIST", JS_ByExampleSkiplist, true);
TRI_AddMethodVocbase(rt, "checksum", JS_ChecksumCollection); TRI_AddMethodVocbase(rt, "checksum", JS_ChecksumCollection);
TRI_AddMethodVocbase(rt, "edges", JS_EdgesQuery); TRI_AddMethodVocbase(rt, "EDGES", JS_EdgesQuery, true);
TRI_AddMethodVocbase(rt, "FIRST", JS_FirstQuery, true); TRI_AddMethodVocbase(rt, "FIRST", JS_FirstQuery, true);
TRI_AddMethodVocbase(rt, "FULLTEXT", JS_FulltextQuery, true); TRI_AddMethodVocbase(rt, "FULLTEXT", JS_FulltextQuery, true);
TRI_AddMethodVocbase(rt, "inEdges", JS_InEdgesQuery); TRI_AddMethodVocbase(rt, "INEDGES", JS_InEdgesQuery, true);
TRI_AddMethodVocbase(rt, "LAST", JS_LastQuery, true); TRI_AddMethodVocbase(rt, "LAST", JS_LastQuery, true);
TRI_AddMethodVocbase(rt, "NEAR", JS_NearQuery, true); TRI_AddMethodVocbase(rt, "NEAR", JS_NearQuery, true);
// internal method. not intended to be used by end-users // internal method. not intended to be used by end-users
TRI_AddMethodVocbase(rt, "OFFSET", JS_OffsetQuery, true); TRI_AddMethodVocbase(rt, "OFFSET", JS_OffsetQuery, true);
TRI_AddMethodVocbase(rt, "outEdges", JS_OutEdgesQuery); TRI_AddMethodVocbase(rt, "OUTEDGES", JS_OutEdgesQuery, true);
TRI_AddMethodVocbase(rt, "WITHIN", JS_WithinQuery); TRI_AddMethodVocbase(rt, "WITHIN", JS_WithinQuery);
} }

View File

@ -225,7 +225,7 @@ static int32_t const WRP_SHAPED_JSON_TYPE = 4;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_CLUSTER #ifdef TRI_ENABLE_CLUSTER
static int parseKeyAndRef (v8::Handle<v8::Value> arg, static int ParseKeyAndRef (v8::Handle<v8::Value> const& arg,
string& key, string& key,
TRI_voc_rid_t& rev) { TRI_voc_rid_t& rev) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData(); TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
@ -234,7 +234,8 @@ static int parseKeyAndRef (v8::Handle<v8::Value> arg,
key = TRI_ObjectToString(arg); key = TRI_ObjectToString(arg);
} }
else if (arg->IsObject()) { else if (arg->IsObject()) {
v8::Handle<v8::Object> obj = arg.As<v8::Object>(); v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(arg);
if (obj->Has(v8g->_KeyKey) && obj->Get(v8g->_KeyKey)->IsString()) { if (obj->Has(v8g->_KeyKey) && obj->Get(v8g->_KeyKey)->IsString()) {
key = TRI_ObjectToString(obj->Get(v8g->_KeyKey)); key = TRI_ObjectToString(obj->Get(v8g->_KeyKey));
} }
@ -468,7 +469,8 @@ static TRI_doc_update_policy_e ExtractUpdatePolicy (v8::Arguments const& argv,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class T> template<class T>
static v8::Handle<v8::Object> WrapClass (v8::Persistent<v8::ObjectTemplate> classTempl, int32_t type, T* y) { static v8::Handle<v8::Object> WrapClass (v8::Persistent<v8::ObjectTemplate> classTempl,
int32_t type, T* y) {
// handle scope for temporary handles // handle scope for temporary handles
v8::HandleScope scope; v8::HandleScope scope;
@ -505,7 +507,7 @@ static inline TRI_vocbase_t* GetContextVocBase () {
/// @brief checks if argument is a document identifier /// @brief checks if argument is a document identifier
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool ParseDocumentHandle (v8::Handle<v8::Value> arg, static bool ParseDocumentHandle (v8::Handle<v8::Value> const& arg,
string& collectionName, string& collectionName,
TRI_voc_key_t& key) { TRI_voc_key_t& key) {
assert(collectionName == ""); assert(collectionName == "");
@ -542,7 +544,7 @@ static bool ParseDocumentHandle (v8::Handle<v8::Value> arg,
/// @brief extracts a document key from a document /// @brief extracts a document key from a document
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static int ExtractDocumentKey (v8::Handle<v8::Value> arg, static int ExtractDocumentKey (v8::Handle<v8::Value> const& arg,
TRI_voc_key_t& key) { TRI_voc_key_t& key) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData(); TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
key = 0; key = 0;
@ -580,11 +582,123 @@ static int ExtractDocumentKey (v8::Handle<v8::Value> arg,
} }
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief parse document or document handle from a v8 value (string | object)
////////////////////////////////////////////////////////////////////////////////
static bool ExtractDocumentHandle (v8::Handle<v8::Value> const& val,
string& collectionName,
TRI_voc_key_t& key,
TRI_voc_rid_t& rid) {
// reset the collection identifier and the revision
collectionName = "";
rid = 0;
// extract the document identifier and revision from a string
if (val->IsString()) {
return ParseDocumentHandle(val, collectionName, key);
}
// extract the document identifier and revision from a document object
if (val->IsObject()) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8::Handle<v8::Object> obj = val->ToObject();
v8::Handle<v8::Value> didVal = obj->Get(v8g->_IdKey);
if (! ParseDocumentHandle(didVal, collectionName, key)) {
return false;
}
if (! obj->Has(v8g->_RevKey)) {
return true;
}
rid = TRI_ObjectToUInt64(obj->Get(v8g->_RevKey), true);
if (rid == 0) {
return false;
}
return true;
}
// unknown value type. give up
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parse document or document handle from a v8 value (string | object)
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> ParseDocumentOrDocumentHandle (CollectionNameResolver const& resolver,
TRI_vocbase_col_t const*& collection,
TRI_voc_key_t& key,
TRI_voc_rid_t& rid,
v8::Handle<v8::Value> const& val) {
v8::HandleScope scope;
assert(key == 0);
// reset the collection identifier and the revision
string collectionName = "";
rid = 0;
// try to extract the collection name, key, and revision from the object passed
if (! ExtractDocumentHandle(val, collectionName, key, rid)) {
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD));
}
// we have at least a key, we also might have a collection name
assert(key != 0);
if (collectionName == "") {
// only a document key without collection name was passed
if (collection == 0) {
// we do not know the collection
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD));
}
// we use the current collection's name
collectionName = resolver.getCollectionName(collection->_cid);
}
else {
// we read a collection name from the document id
// check cross-collection requests
if (collection != 0) {
if (collectionName != resolver.getCollectionName(collection->_cid) &&
collectionName != StringUtils::itoa(collection->_cid)) {
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST));
}
}
}
assert(collectionName != "");
if (collection == 0) {
// no collection object was passed, now check the user-supplied collection name
const TRI_vocbase_col_t* col = resolver.getCollectionStruct(collectionName);
if (col == 0) {
// collection not found
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND));
}
collection = col;
}
assert(collection != 0);
v8::Handle<v8::Value> empty;
return scope.Close(empty);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief checks if argument is an index identifier /// @brief checks if argument is an index identifier
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool IsIndexHandle (v8::Handle<v8::Value> arg, static bool IsIndexHandle (v8::Handle<v8::Value> const& arg,
string& collectionName, string& collectionName,
TRI_idx_iid_t& iid) { TRI_idx_iid_t& iid) {
@ -1673,7 +1787,7 @@ static v8::Handle<v8::Value> DocumentVocbaseCol_Coordinator (
string key; string key;
TRI_voc_rid_t rev = 0; TRI_voc_rid_t rev = 0;
int error = parseKeyAndRef(argv[0], key, rev); int error = ParseKeyAndRef(argv[0], key, rev);
if (error != TRI_ERROR_NO_ERROR) { if (error != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, error); TRI_V8_EXCEPTION(scope, error);
} }
@ -1795,7 +1909,7 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
#endif #endif
CollectionNameResolver resolver(vocbase); CollectionNameResolver resolver(vocbase);
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]); v8::Handle<v8::Value> err = ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
if (key == 0) { if (key == 0) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD); TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
@ -1911,7 +2025,7 @@ static v8::Handle<v8::Value> ExistsVocbaseCol (const bool useCollection,
#endif #endif
CollectionNameResolver resolver(vocbase); CollectionNameResolver resolver(vocbase);
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]); v8::Handle<v8::Value> err = ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
if (key == 0) { if (key == 0) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD); TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
@ -1996,7 +2110,7 @@ static v8::Handle<v8::Value> ModifyVocbaseCol_Coordinator (
string key; string key;
TRI_voc_rid_t rev = 0; TRI_voc_rid_t rev = 0;
int error = parseKeyAndRef(argv[0], key, rev); int error = ParseKeyAndRef(argv[0], key, rev);
if (error != TRI_ERROR_NO_ERROR) { if (error != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, error); TRI_V8_EXCEPTION(scope, error);
} }
@ -2111,7 +2225,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
#endif #endif
CollectionNameResolver resolver(vocbase); CollectionNameResolver resolver(vocbase);
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]); v8::Handle<v8::Value> err = ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
if (key == 0) { if (key == 0) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD); TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
@ -2342,44 +2456,28 @@ static v8::Handle<v8::Value> SaveEdgeCol (
TRI_document_edge_t edge; TRI_document_edge_t edge;
// the following values are defaults that will be overridden below // the following values are defaults that will be overridden below
edge._fromCid = trx->cid(); edge._fromCid = 0;
edge._toCid = trx->cid(); edge._toCid = 0;
edge._fromKey = 0; edge._fromKey = 0;
edge._toKey = 0; edge._toKey = 0;
v8::Handle<v8::Value> err;
// extract from // extract from
TRI_vocbase_col_t const* fromCollection = 0; res = TRI_ParseVertex(resolver, edge._fromCid, edge._fromKey, argv[0], false);
TRI_voc_rid_t fromRid;
err = TRI_ParseDocumentOrDocumentHandle(resolver, fromCollection, edge._fromKey, fromRid, argv[0]); if (res != TRI_ERROR_NO_ERROR) {
if (! err.IsEmpty()) {
if (edge._fromKey != 0) {
TRI_Free(TRI_CORE_MEM_ZONE, edge._fromKey);
}
FREE_STRING(TRI_CORE_MEM_ZONE, key); FREE_STRING(TRI_CORE_MEM_ZONE, key);
return scope.Close(v8::ThrowException(err)); TRI_V8_EXCEPTION(scope, res);
} }
edge._fromCid = fromCollection->_cid;
// extract to // extract to
TRI_vocbase_col_t const* toCollection = 0; res = TRI_ParseVertex(resolver, edge._toCid, edge._toKey, argv[1], false);
TRI_voc_rid_t toRid;
if (res != TRI_ERROR_NO_ERROR) {
err = TRI_ParseDocumentOrDocumentHandle(resolver, toCollection, edge._toKey, toRid, argv[1]);
if (! err.IsEmpty()) {
FREE_STRING(TRI_CORE_MEM_ZONE, edge._fromKey); FREE_STRING(TRI_CORE_MEM_ZONE, edge._fromKey);
FREE_STRING(TRI_CORE_MEM_ZONE, edge._toKey);
FREE_STRING(TRI_CORE_MEM_ZONE, key); FREE_STRING(TRI_CORE_MEM_ZONE, key);
return scope.Close(v8::ThrowException(err)); TRI_V8_EXCEPTION(scope, res);
} }
edge._toCid = toCollection->_cid;
TRI_primary_collection_t* primary = trx->primaryCollection(); TRI_primary_collection_t* primary = trx->primaryCollection();
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone; TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
@ -2472,7 +2570,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (const bool useCollection,
#endif #endif
CollectionNameResolver resolver(vocbase); CollectionNameResolver resolver(vocbase);
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]); v8::Handle<v8::Value> err = ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
if (! err.IsEmpty()) { if (! err.IsEmpty()) {
FREE_STRING(TRI_CORE_MEM_ZONE, key); FREE_STRING(TRI_CORE_MEM_ZONE, key);
@ -2600,7 +2698,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol_Coordinator (
string key; string key;
TRI_voc_rid_t rev = 0; TRI_voc_rid_t rev = 0;
int error = parseKeyAndRef(argv[0], key, rev); int error = ParseKeyAndRef(argv[0], key, rev);
if (error != TRI_ERROR_NO_ERROR) { if (error != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, error); TRI_V8_EXCEPTION(scope, error);
} }
@ -2698,7 +2796,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (const bool useCollection,
#endif #endif
CollectionNameResolver resolver(vocbase); CollectionNameResolver resolver(vocbase);
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]); v8::Handle<v8::Value> err = ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
if (key == 0) { if (key == 0) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD); TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
@ -5998,7 +6096,7 @@ static v8::Handle<v8::Value> JS_DropVocbaseCol_Coordinator (TRI_vocbase_col_t* c
ClusterInfo* ci = ClusterInfo::instance(); ClusterInfo* ci = ClusterInfo::instance();
string errorMsg; string errorMsg;
int myerrno = ci->dropCollectionCoordinator( databaseName, cid, int myerrno = ci->dropCollectionCoordinator( databaseName, cid,
errorMsg, 120.0); errorMsg, 120.0);
if (myerrno != TRI_ERROR_NO_ERROR) { if (myerrno != TRI_ERROR_NO_ERROR) {
@ -9543,113 +9641,57 @@ static v8::Handle<v8::Value> MapGetIndexedShapedJson (uint32_t idx,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief parse document or document handle from a v8 value (string | object) /// @brief parse vertex handle from a v8 value (string | object)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool ExtractDocumentHandle (v8::Handle<v8::Value> val, int TRI_ParseVertex (CollectionNameResolver const& resolver,
string& collectionName, TRI_voc_cid_t& cid,
TRI_voc_key_t& key, TRI_voc_key_t& key,
TRI_voc_rid_t& rid) { v8::Handle<v8::Value> const& val,
// reset the collection identifier and the revision bool translateName) {
collectionName = "";
rid = 0;
// extract the document identifier and revision from a string
if (val->IsString()) {
return ParseDocumentHandle(val, collectionName, key);
}
// extract the document identifier and revision from a document object
if (val->IsObject()) {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8::Handle<v8::Object> obj = val->ToObject();
v8::Handle<v8::Value> didVal = obj->Get(v8g->_IdKey);
if (! ParseDocumentHandle(didVal, collectionName, key)) {
return false;
}
if (! obj->Has(v8g->_RevKey)) {
return true;
}
rid = TRI_ObjectToUInt64(obj->Get(v8g->_RevKey), true);
if (rid == 0) {
return false;
}
return true;
}
// unknown value type. give up
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parse document or document handle from a v8 value (string | object)
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (const CollectionNameResolver& resolver,
TRI_vocbase_col_t const*& collection,
TRI_voc_key_t& key,
TRI_voc_rid_t& rid,
v8::Handle<v8::Value> val) {
v8::HandleScope scope; v8::HandleScope scope;
assert(key == 0); assert(key == 0);
// reset the collection identifier and the revision // reset everything
string collectionName = ""; string collectionName = "";
rid = 0; TRI_voc_rid_t rid = 0;
// try to extract the collection name, key, and revision from the object passed // try to extract the collection name, key, and revision from the object passed
if (! ExtractDocumentHandle(val, collectionName, key, rid)) { if (! ExtractDocumentHandle(val, collectionName, key, rid)) {
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD)); return TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD;
} }
// we have at least a key, we also might have a collection name // we have at least a key, we also might have a collection name
assert(key != 0); assert(key != 0);
if (collectionName == "") { if (collectionName == "") {
// only a document key without collection name was passed // we do not know the collection
if (collection == 0) { TRI_FreeString(TRI_CORE_MEM_ZONE, key);
// we do not know the collection key = 0;
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD));
} return TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD;
// we use the current collection's name }
collectionName = resolver.getCollectionName(collection->_cid);
#ifdef TRI_ENABLE_CLUSTER
if (translateName && ServerState::instance()->isDBserver()) {
cid = resolver.getCollectionIdCluster(collectionName);
} }
else { else {
// we read a collection name from the document id cid = resolver.getCollectionId(collectionName);
// check cross-collection requests }
if (collection != 0) { #else
if (collectionName != resolver.getCollectionName(collection->_cid) && cid = resolver.getCollectionId(collectionName);
collectionName != StringUtils::itoa(collection->_cid)) { #endif
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST));
} if (cid == 0) {
} TRI_FreeString(TRI_CORE_MEM_ZONE, key);
key = 0;
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
} }
assert(collectionName != ""); return TRI_ERROR_NO_ERROR;
if (collection == 0) {
// no collection object was passed, now check the user-supplied collection name
const TRI_vocbase_col_t* col = resolver.getCollectionStruct(collectionName);
if (col == 0) {
// collection not found
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND));
}
collection = col;
}
assert(collection != 0);
v8::Handle<v8::Value> empty;
return scope.Close(empty);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -54,14 +54,14 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief parse document or document handle /// @brief parse vertex handle from a v8 value (string | object)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (const triagens::arango::CollectionNameResolver&, int TRI_ParseVertex (triagens::arango::CollectionNameResolver const&,
TRI_vocbase_col_t const*&, TRI_voc_cid_t&,
TRI_voc_key_t&, TRI_voc_key_t&,
TRI_voc_rid_t&, v8::Handle<v8::Value> const&,
v8::Handle<v8::Value>); bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a index identifier /// @brief looks up a index identifier

View File

@ -147,8 +147,7 @@ function get_edges (req, res) {
} }
var name = decodeURIComponent(req.suffix[0]); var name = decodeURIComponent(req.suffix[0]);
var id = parseInt(name, 10) || name; var collection = arangodb.db._collection(name);
var collection = arangodb.db._collection(id);
if (collection === null) { if (collection === null) {
actions.collectionNotFound(req, res, name); actions.collectionNotFound(req, res, name);
@ -162,10 +161,10 @@ function get_edges (req, res) {
if (direction === null || direction === undefined || direction === "" || direction === "any") { if (direction === null || direction === undefined || direction === "" || direction === "any") {
e = collection.edges(vertex); e = collection.edges(vertex);
} }
else if (direction === "in") { else if (direction === "in" || direction === "inbound") {
e = collection.inEdges(vertex); e = collection.inEdges(vertex);
} }
else if (direction === "out") { else if (direction === "out" || direction === "outbound") {
e = collection.outEdges(vertex); e = collection.outEdges(vertex);
} }
else { else {
@ -173,14 +172,12 @@ function get_edges (req, res) {
"<direction> must be any, in, or out, not: " + JSON.stringify(direction)); "<direction> must be any, in, or out, not: " + JSON.stringify(direction));
return; return;
} }
var result = { edges : e }; actions.resultOk(req, res, actions.HTTP_OK, { edges: e });
actions.resultOk(req, res, actions.HTTP_OK, result);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief reads or creates a collection /// @brief gateway
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({ actions.defineHttp({

View File

@ -188,6 +188,95 @@ ArangoCollection.prototype.index = function (id) {
throw err; throw err;
}; };
// -----------------------------------------------------------------------------
// --SECTION-- edge functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief returns connected edges
////////////////////////////////////////////////////////////////////////////////
function getEdges (collection, vertex, direction) {
var cluster = require("org/arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, collection.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
shards.forEach(function (shard) {
var url = "/_api/edges/" + encodeURIComponent(shard) +
"?direction=" + encodeURIComponent(direction) +
"&vertex=" + encodeURIComponent(vertex);
ArangoClusterComm.asyncRequest("get",
"shard:" + shard,
dbName,
url,
"",
{ },
options);
});
var results = cluster.wait(coord, shards), i;
var edges = [ ];
for (i = 0; i < results.length; ++i) {
var body = JSON.parse(results[i].body);
edges = edges.concat(body.edges);
}
return edges;
}
if (direction === "in") {
return collection.INEDGES(vertex);
}
if (direction === "out") {
return collection.OUTEDGES(vertex);
}
return collection.EDGES(vertex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns all edges connected to a vertex
///
/// @FUN{@FA{collection}.edges(@FA{vertex-id})}
///
/// Returns all edges connected to the vertex specified by @FA{vertex-id}.
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.edges = function (vertex) {
return getEdges(this, vertex, "any");
};
////////////////////////////////////////////////////////////////////////////////
/// @brief returns inbound edges connected to a vertex
///
/// @FUN{@FA{collection}.edges(@FA{vertex-id})}
///
/// Returns inbound edges connected to the vertex specified by @FA{vertex-id}.
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.inEdges = function (vertex) {
return getEdges(this, vertex, "in");
};
////////////////////////////////////////////////////////////////////////////////
/// @brief returns outbound edges connected to a vertex
///
/// @FUN{@FA{collection}.edges(@FA{vertex-id})}
///
/// Returns outbound edges connected to the vertex specified by @FA{vertex-id}.
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.outEdges = function (vertex) {
return getEdges(this, vertex, "out");
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- document functions // --SECTION-- document functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------