1
0
Fork 0

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

This commit is contained in:
Max Neunhoeffer 2014-05-23 10:32:35 +02:00
commit 45a687dbd1
29 changed files with 1432 additions and 2565 deletions

View File

@ -196,7 +196,7 @@
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', # -Werror
'GCC_VERSION': 'com.apple.compilers.llvmgcc42',
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'NO', # -Wnewline-eof
# MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
'PREBINDING': 'NO', # No -Wl,-prebind

View File

@ -59,6 +59,13 @@ For a list of available methods for the `db` object, type
arangosh> db._help();
Note that it also possible to execute scripts in arangosh and pass parameters
to the file, e.g.:
> arangosh --javascript.execute myscript.js parameter1 parameter2
Inside the script you can use the "ARGUMENTS" array to access the parameters.
ArangoDB Shell Output {#UserManualArangoshOutput}
=================================================

View File

@ -712,9 +712,9 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
REGISTER_FUNCTION("TRAVERSAL_TREE", "GRAPH_TRAVERSAL_TREE", false, false, "h,h,s,s,s|a", NULL);
REGISTER_FUNCTION("GRAPH_TRAVERSAL_TREE", "GENERAL_GRAPH_TRAVERSAL_TREE", false, false, "s,s,s,s|a", NULL);
REGISTER_FUNCTION("EDGES", "GRAPH_EDGES", false, false, "h,s,s|l", NULL);
REGISTER_FUNCTION("GRAPH_EDGES", "GENERAL_GRAPH_EDGES", false, false, "s,s,s|lza,ls", NULL);
REGISTER_FUNCTION("GRAPH_EDGES", "GENERAL_GRAPH_EDGES", false, false, "s,as|a", NULL);
REGISTER_FUNCTION("NEIGHBORS", "GRAPH_NEIGHBORS", false, false, "h,h,s,s|l", NULL);
REGISTER_FUNCTION("GRAPH_NEIGHBORS", "GENERAL_GRAPH_NEIGHBORS", false, false, "s,s,s|l", NULL);
REGISTER_FUNCTION("GRAPH_NEIGHBORS", "GENERAL_GRAPH_NEIGHBORS", false, false, "s,as|a", NULL);
// date functions
REGISTER_FUNCTION("DATE_NOW", "DATE_NOW", false, false, "", NULL); // NOW is non-deterministic

View File

@ -281,7 +281,7 @@ static int SetupExampleObject (v8::Handle<v8::Object> const example,
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
values[i] = TRI_ShapedJsonV8Object(val, shaper, false, false);
values[i] = TRI_ShapedJsonV8Object(val, shaper, false);
if (values[i] == 0) {
CleanupExampleObject(shaper->_memoryZone, i, pids, values);
@ -995,10 +995,10 @@ static int SetupSearchValue (TRI_vector_t const* paths,
if (example->HasOwnProperty(key)) {
v8::Handle<v8::Value> val = example->Get(key);
res = TRI_FillShapedJsonV8Object(val, &result._values[i], shaper, false, false);
res = TRI_FillShapedJsonV8Object(val, &result._values[i], shaper, false);
}
else {
res = TRI_FillShapedJsonV8Object(v8::Null(), &result._values[i], shaper, false, false);
res = TRI_FillShapedJsonV8Object(v8::Null(), &result._values[i], shaper, false);
}
if (res != TRI_ERROR_NO_ERROR) {

View File

@ -413,31 +413,6 @@ static bool ExtractForceSync (v8::Arguments const& argv,
return forceSync;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extract the update policy from the arguments
/// must specify the argument index starting from 1
////////////////////////////////////////////////////////////////////////////////
static TRI_doc_update_policy_e ExtractUpdatePolicy (v8::Arguments const& argv,
const int index) {
assert(index > 0);
// default value
TRI_doc_update_policy_e policy = TRI_DOC_UPDATE_ERROR;
if (argv.Length() >= index) {
if (TRI_ObjectToBoolean(argv[index - 1])) {
// overwrite!
policy = TRI_DOC_UPDATE_LAST_WRITE;
}
else {
policy = TRI_DOC_UPDATE_CONFLICT;
}
}
return policy;
}
TRI_doc_update_policy_e ExtractUpdatePolicy (bool overwrite) {
TRI_doc_update_policy_e policy ;
@ -2333,7 +2308,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (bool useCollection,
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, old);
}
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[1], primary->_shaper, true, true);
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[1], primary->_shaper, true);
if (shaped == 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
@ -2401,7 +2376,7 @@ static v8::Handle<v8::Value> SaveVocbaseCol (
trx->lockWrite();
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper, true, true);
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper, true);
if (shaped == 0) {
FREE_STRING(TRI_CORE_MEM_ZONE, key);
@ -2519,7 +2494,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (
trx->lockWrite();
// extract shaped data
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], primary->_shaper, true, true);
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], primary->_shaper, true);
if (shaped == 0) {
FREE_STRING(TRI_CORE_MEM_ZONE, edge._fromKey);
@ -2826,6 +2801,16 @@ static v8::Handle<v8::Value> RemoveVocbaseColCoordinator (TRI_vocbase_col_t cons
return scope.Close(v8::True());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief internal struct which is used for reading the different option
/// parameters for the remove function
////////////////////////////////////////////////////////////////////////////////
struct RemoveOptions {
bool overwrite = true;
bool waitForSync = false;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes a document
////////////////////////////////////////////////////////////////////////////////
@ -2833,14 +2818,36 @@ static v8::Handle<v8::Value> RemoveVocbaseColCoordinator (TRI_vocbase_col_t cons
static v8::Handle<v8::Value> RemoveVocbaseCol (bool useCollection,
v8::Arguments const& argv) {
v8::HandleScope scope;
ReplaceOptions options;
TRI_doc_update_policy_e policy = TRI_DOC_UPDATE_ERROR;
// check the arguments
if (argv.Length() < 1 || argv.Length() > 3) {
TRI_V8_EXCEPTION_USAGE(scope, "remove(<document>, <overwrite>, <waitForSync>)");
TRI_V8_EXCEPTION_USAGE(scope, "remove(<document>, <overwrite>, <waitForSync>) or"
"remove(<document>, <data>, {overwrite: booleanValue, waitForSync: booleanValue})"
);
}
const TRI_doc_update_policy_e policy = ExtractUpdatePolicy(argv, 2);
const bool forceSync = ExtractForceSync(argv, 3);
if (argv.Length() > 1) {
if (argv[1]->IsObject()) {
v8::Handle<v8::Object> optionsObject = argv[1].As<v8::Object>();
if (optionsObject->Has(v8::String::New("overwrite"))) {
options.overwrite = TRI_ObjectToBoolean(optionsObject->Get(v8::String::New("overwrite")));
policy = ExtractUpdatePolicy(options.overwrite);
}
if (optionsObject->Has(v8::String::New("waitForSync"))) {
options.waitForSync = TRI_ObjectToBoolean(optionsObject->Get(v8::String::New("waitForSync")));
}
} else {// old variant replace(<document>, <data>, <overwrite>, <waitForSync>)
if (argv.Length() > 1 ) {
options.overwrite = TRI_ObjectToBoolean(argv[1]);
policy = ExtractUpdatePolicy(options.overwrite);
}
if (argv.Length() > 2 ) {
options.waitForSync = TRI_ObjectToBoolean(argv[2]);
}
}
}
TRI_voc_key_t key = 0;
TRI_voc_rid_t rid;
@ -2885,7 +2892,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (bool useCollection,
assert(key != 0);
if (ServerState::instance()->isCoordinator()) {
return scope.Close(RemoveVocbaseColCoordinator(col, policy, forceSync, argv));
return scope.Close(RemoveVocbaseColCoordinator(col, policy, options.waitForSync, argv));
}
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, resolver, col->_cid);
@ -2896,7 +2903,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (bool useCollection,
TRI_V8_EXCEPTION(scope, res);
}
res = trx.deleteDocument(key, policy, forceSync, rid, &actualRevision);
res = trx.deleteDocument(key, policy, options.waitForSync, rid, &actualRevision);
res = trx.finish(res);
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
@ -8578,7 +8585,9 @@ static v8::Handle<v8::Value> JS_CreateEdgeCollectionVocbase (v8::Arguments const
/// existed and was deleted. It returns @LIT{false}, if the document was already
/// deleted.
///
/// @FUN{@FA{db}._remove(@FA{document}, true, @FA{waitForSync})}
/// @FUN{@FA{db}._remove(@FA{document}, true, @FA{waitForSync})} or
/// @FUN{@FA{db}._remove(@FA{document},
/// {@FA{overwrite}: true or false, @FA{waitForSynca}: true or false})}
///
/// The optional @FA{waitForSync} parameter can be used to force synchronisation
/// of the document deletion operation to disk even in case that the
@ -8631,6 +8640,17 @@ static v8::Handle<v8::Value> JS_CreateEdgeCollectionVocbase (v8::Arguments const
/// !db._document(a1);
/// ! ^
/// @endcode
/// Remove a document using new signature:
/// @code
/// arangod> db.example.save({ a: 1 } );
/// {
// "_id" : "example/11265325374",
// "_rev" : "11265325374",
// "_key" : "11265325374"
// }
// arangod> db.example.remove("example/11265325374", {overwrite: true, waitForSync: false})
// true
/// @endcode
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_RemoveVocbase (v8::Arguments const& argv) {

View File

@ -412,13 +412,52 @@ typedef struct TRI_df_footer_marker_s {
TRI_df_footer_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief datafile document marker
/// @brief begin transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_df_document_marker_s {
TRI_df_marker_t base; // 24 bytes
typedef struct TRI_doc_begin_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
uint32_t _numCollections;
#ifdef TRI_PADDING_32
char _padding_begin_marker[4];
#endif
}
TRI_df_document_marker_t;
TRI_doc_begin_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief commit transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_commit_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_commit_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief abort transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_abort_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_abort_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief prepare transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_prepare_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_prepare_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @}

File diff suppressed because it is too large Load Diff

View File

@ -147,7 +147,6 @@ typedef struct TRI_transaction_operation_s {
TRI_doc_mptr_t* _newHeader;
TRI_doc_mptr_t* _oldHeader;
TRI_doc_mptr_t _oldData;
TRI_df_marker_t* _marker;
TRI_voc_document_operation_e _type;
}
TRI_transaction_operation_t;
@ -271,19 +270,6 @@ int TRI_WriteMarkerDocumentCollection (TRI_document_collection_t*,
struct TRI_df_marker_s**,
const bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief writes a document operation marker into the datafile
////////////////////////////////////////////////////////////////////////////////
int TRI_WriteOperationDocumentCollection (TRI_document_collection_t*,
TRI_voc_document_operation_e,
TRI_doc_mptr_t*,
TRI_doc_mptr_t*,
TRI_doc_mptr_t*,
TRI_df_marker_t*,
struct TRI_df_marker_s**,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new journal
////////////////////////////////////////////////////////////////////////////////

View File

@ -1272,7 +1272,7 @@ static int HandleTransaction (TRI_replication_logger_t* logger,
buffer,
document,
trxOperation->_type,
trxOperation->_marker,
nullptr, // TODO: fix this: replication is broken otherwise!! trxOperation->_marker,
trxOperation->_oldHeader,
true)) {
ReturnBuffer(logger, buffer);

File diff suppressed because it is too large Load Diff

View File

@ -200,15 +200,15 @@ void TRI_IncreaseWritesCollectionTransaction (TRI_transaction_collection_t*,
////////////////////////////////////////////////////////////////////////////////
bool TRI_WasSynchronousCollectionTransaction (TRI_transaction_t const*,
const TRI_voc_cid_t);
TRI_voc_cid_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief return the collection from a transaction
////////////////////////////////////////////////////////////////////////////////
TRI_transaction_collection_t* TRI_GetCollectionTransaction (TRI_transaction_t const*,
const TRI_voc_cid_t,
const TRI_transaction_type_e);
TRI_voc_cid_t,
TRI_transaction_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to a transaction
@ -259,37 +259,14 @@ int TRI_AddOperationTransaction (TRI_transaction_collection_t*,
struct TRI_doc_mptr_s*,
struct TRI_doc_mptr_s*,
struct TRI_doc_mptr_s*,
void const*,
TRI_voc_rid_t,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a marker to a transaction collection
////////////////////////////////////////////////////////////////////////////////
int TRI_AddOperationCollectionTransaction (TRI_transaction_collection_t*,
TRI_voc_document_operation_e,
struct TRI_doc_mptr_s*,
struct TRI_doc_mptr_s*,
struct TRI_doc_mptr_s*,
TRI_df_marker_t*,
TRI_voc_rid_t,
bool,
bool*);
////////////////////////////////////////////////////////////////////////////////
/// @brief get a transaction's id
////////////////////////////////////////////////////////////////////////////////
TRI_voc_tid_t TRI_GetIdTransaction (TRI_transaction_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief get a transaction's id for writing into a marker
/// this will return 0 if the operation is standalone
////////////////////////////////////////////////////////////////////////////////
TRI_voc_tid_t TRI_GetMarkerIdTransaction (TRI_transaction_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief begin a transaction
////////////////////////////////////////////////////////////////////////////////
@ -312,111 +289,6 @@ int TRI_CommitTransaction (TRI_transaction_t*,
int TRI_AbortTransaction (TRI_transaction_t*,
int);
// -----------------------------------------------------------------------------
// --SECTION-- TRANSACTION HELPERS
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a single operation wrapped in a transaction
/// the actual operation can be specified using a callback function
////////////////////////////////////////////////////////////////////////////////
int TRI_ExecuteSingleOperationTransaction (struct TRI_vocbase_s*,
const char*,
TRI_transaction_type_e,
int (*callback)(TRI_transaction_collection_t*, void*),
void*,
bool);
// -----------------------------------------------------------------------------
// --SECTION-- TRANSACTION MARKERS
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief begin transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_begin_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
uint32_t _numCollections;
#ifdef TRI_PADDING_32
char _padding_begin_marker[4];
#endif
}
TRI_doc_begin_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief commit transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_commit_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_commit_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief abort transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_abort_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_abort_transaction_marker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief prepare transaction marker
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_doc_prepare_transaction_marker_s {
TRI_df_marker_t base;
TRI_voc_tid_t _tid;
}
TRI_doc_prepare_transaction_marker_t;
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create a "begin" marker
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateMarkerBeginTransaction (TRI_transaction_t*,
struct TRI_doc_begin_transaction_marker_s**,
uint32_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief create a "commit" marker
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateMarkerCommitTransaction (TRI_transaction_t*,
struct TRI_doc_commit_transaction_marker_s**);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an "abort" marker
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateMarkerAbortTransaction (TRI_transaction_t*,
struct TRI_doc_abort_transaction_marker_s**);
////////////////////////////////////////////////////////////////////////////////
/// @brief create a "prepare" marker
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateMarkerPrepareTransaction (TRI_transaction_t*,
struct TRI_doc_prepare_transaction_marker_s**);
#endif
// Local Variables:

View File

@ -28,6 +28,8 @@
#include "voc-shaper.h"
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "BasicsC/associative.h"
#include "BasicsC/hashes.h"
#include "BasicsC/locks.h"
@ -35,6 +37,7 @@
#include "BasicsC/tri-strings.h"
#include "BasicsC/utf8-helper.h"
#include "VocBase/document-collection.h"
#include "Wal/LogfileManager.h"
// -----------------------------------------------------------------------------
// --SECTION-- private types
@ -54,14 +57,14 @@ typedef struct voc_shaper_s {
TRI_associative_pointer_t _accessors;
TRI_shape_aid_t _nextAid;
TRI_shape_sid_t _nextSid;
std::atomic<TRI_shape_aid_t> _nextAid;
std::atomic<TRI_shape_sid_t> _nextSid;
TRI_document_collection_t* _collection;
TRI_mutex_t _shapeLock;
TRI_mutex_t _attributeLock;
TRI_mutex_t _accessorLock;
triagens::basics::Mutex _accessorLock;
triagens::basics::Mutex _shapeLock;
triagens::basics::Mutex _attributeLock;
}
voc_shaper_t;
@ -69,6 +72,44 @@ voc_shaper_t;
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief extracts an attribute id from a marker
////////////////////////////////////////////////////////////////////////////////
static inline TRI_shape_aid_t GetAttributeId (void const* marker) {
TRI_df_marker_t const* p = static_cast<TRI_df_marker_t const*>(marker);
if (p != nullptr) {
if (p->_type == TRI_DF_MARKER_ATTRIBUTE) {
return reinterpret_cast<TRI_df_attribute_marker_t const*>(p)->_aid;
}
else if (p->_type == TRI_WAL_MARKER_ATTRIBUTE) {
return reinterpret_cast<triagens::wal::attribute_marker_t const*>(p)->_attributeId;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extracts an attribute name from a marker
////////////////////////////////////////////////////////////////////////////////
static inline char const* GetAttributeName (void const* marker) {
TRI_df_marker_t const* p = static_cast<TRI_df_marker_t const*>(marker);
if (p != nullptr) {
if (p->_type == TRI_DF_MARKER_ATTRIBUTE) {
return reinterpret_cast<char const*>(p) + sizeof(TRI_df_attribute_marker_t);
}
else if (p->_type == TRI_WAL_MARKER_ATTRIBUTE) {
return reinterpret_cast<char const*>(p) + sizeof(triagens::wal::attribute_marker_t);
}
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the attribute name of a key
////////////////////////////////////////////////////////////////////////////////
@ -84,9 +125,7 @@ static uint64_t HashKeyAttributeName (TRI_associative_synced_t* array, void cons
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementAttributeName (TRI_associative_synced_t* array, void const* element) {
char const* e = (char const*) element;
return TRI_FnvHashString(e + sizeof(TRI_df_attribute_marker_t));
return TRI_FnvHashString(GetAttributeName(element));
}
////////////////////////////////////////////////////////////////////////////////
@ -95,9 +134,8 @@ static uint64_t HashElementAttributeName (TRI_associative_synced_t* array, void
static bool EqualKeyAttributeName (TRI_associative_synced_t* array, void const* key, void const* element) {
char const* k = (char const*) key;
char const* e = (char const*) element;
return TRI_EqualString(k, e + sizeof(TRI_df_attribute_marker_t));
return TRI_EqualString(k, GetAttributeName(element));
}
////////////////////////////////////////////////////////////////////////////////
@ -106,16 +144,13 @@ static bool EqualKeyAttributeName (TRI_associative_synced_t* array, void const*
static TRI_shape_aid_t LookupAttributeByName (TRI_shaper_t* shaper,
char const* name) {
voc_shaper_t* s;
void const* p;
assert(name != nullptr);
assert(name != NULL);
voc_shaper_t* s = reinterpret_cast<voc_shaper_t*>(shaper);
void const* p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
s = (voc_shaper_t*) shaper;
p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
if (p != NULL) {
return ((TRI_df_attribute_marker_t const*) p)->_aid;
if (p != nullptr) {
return GetAttributeId(p);
}
return 0;
@ -126,115 +161,52 @@ static TRI_shape_aid_t LookupAttributeByName (TRI_shaper_t* shaper,
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_aid_t FindOrCreateAttributeByName (TRI_shaper_t* shaper,
char const* name,
bool isLocked) {
char* mem;
TRI_df_attribute_marker_t* marker;
TRI_df_marker_t* result;
TRI_doc_datafile_info_t* dfi;
TRI_voc_fid_t fid;
int res;
size_t n;
voc_shaper_t* s;
TRI_shape_aid_t aid;
TRI_voc_size_t totalSize;
void const* p;
void* f;
char const* name) {
// check if the attribute exists
TRI_shape_aid_t aid = LookupAttributeByName(shaper, name);
assert(name != nullptr);
s = (voc_shaper_t*) shaper;
p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
if (p != nullptr) {
return ((TRI_df_attribute_marker_t const*) p)->_aid;
if (aid != 0) {
// yes
return aid;
}
// create a new attribute name
n = strlen(name) + 1;
totalSize = (TRI_voc_size_t) (sizeof(TRI_df_attribute_marker_t) + n);
mem = (char*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, totalSize, false);
// we need to create a new attribute marker
if (mem == nullptr) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return 0;
}
// marker points to mem, but has a different type
marker = (TRI_df_attribute_marker_t*) mem;
assert(marker != nullptr);
// init attribute marker
TRI_InitMarker(mem, TRI_DF_MARKER_ATTRIBUTE, totalSize);
// copy attribute name into marker
memcpy(mem + sizeof(TRI_df_attribute_marker_t), name, n);
marker->_size = n;
// lock the index and check that the element is still missing
TRI_LockMutex(&s->_attributeLock);
p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
// if the element appeared, return the aid
if (p != nullptr) {
TRI_UnlockMutex(&s->_attributeLock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
return ((TRI_df_attribute_marker_t const*) p)->_aid;
}
// get next attribute id and write into marker
// increase attribute id value
voc_shaper_t* s = reinterpret_cast<voc_shaper_t*>(shaper);
aid = s->_nextAid++;
marker->_aid = aid;
TRI_primary_collection_t* primary = &s->_collection->base;
triagens::wal::AttributeMarker marker(primary->base._vocbase->_id, primary->base._info._cid, aid, std::string(name));
if (! isLocked) {
// write-lock
s->_collection->base.beginWrite(&s->_collection->base);
// lock the index and check that the element is still missing
{
MUTEX_LOCKER(s->_attributeLock);
void const* p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
// if the element appeared, return the aid
if (p != nullptr) {
return GetAttributeId(p);
}
// write marker into wal
triagens::wal::SlotInfo slotInfo = triagens::wal::LogfileManager::instance()->writeMarker(marker, false);
if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) {
LOG_WARNING("could not save attribute marker in log");
return 0;
}
void* f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast<void*>(slotInfo.mem), false);
assert(f == nullptr);
// enter into the dictionaries
f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, const_cast<void*>(slotInfo.mem), false);
assert(f == nullptr);
}
// write attribute into the collection
res = TRI_WriteMarkerDocumentCollection(s->_collection, &marker->base, totalSize, &fid, &result, false);
if (! isLocked) {
s->_collection->base.endWrite(&s->_collection->base);
}
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
if (res != TRI_ERROR_NO_ERROR) {
TRI_UnlockMutex(&s->_attributeLock);
LOG_ERROR("an error occurred while writing attribute data into shapes collection: %s",
TRI_errno_string(res));
return 0;
}
assert(result != nullptr);
// update datafile info
dfi = TRI_FindDatafileInfoPrimaryCollection(&s->_collection->base, fid, true);
if (dfi != nullptr) {
dfi->_numberAttributes++;
dfi->_sizeAttributes += (int64_t) TRI_DF_ALIGN_BLOCK(totalSize);
}
f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, result, false);
assert(f == nullptr);
// enter into the dictionaries
f = TRI_InsertKeyAssociativeSynced(&s->_attributeNames, name, result, false);
assert(f == nullptr);
// ...........................................................................
// and release the lock
// ...........................................................................
TRI_UnlockMutex(&s->_attributeLock);
return aid;
}
@ -253,9 +225,9 @@ static uint64_t HashKeyAttributeId (TRI_associative_synced_t* array, void const*
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementAttributeId (TRI_associative_synced_t* array, void const* element) {
TRI_df_attribute_marker_t const* e = static_cast<TRI_df_attribute_marker_t const*>(element);
TRI_shape_aid_t aid = GetAttributeId(element);
return TRI_FnvHashPointer(&e->_aid, sizeof(TRI_shape_aid_t));
return TRI_FnvHashPointer(&aid, sizeof(TRI_shape_aid_t));
}
////////////////////////////////////////////////////////////////////////////////
@ -264,9 +236,9 @@ static uint64_t HashElementAttributeId (TRI_associative_synced_t* array, void co
static bool EqualKeyAttributeId (TRI_associative_synced_t* array, void const* key, void const* element) {
TRI_shape_aid_t const* k = static_cast<TRI_shape_aid_t const*>(key);
TRI_df_attribute_marker_t const* e = static_cast<TRI_df_attribute_marker_t const*>(element);
TRI_shape_aid_t aid = GetAttributeId(element);
return *k == e->_aid;
return *k == aid;
}
////////////////////////////////////////////////////////////////////////////////
@ -276,14 +248,13 @@ static bool EqualKeyAttributeId (TRI_associative_synced_t* array, void const* ke
static char const* LookupAttributeId (TRI_shaper_t* shaper,
TRI_shape_aid_t aid) {
voc_shaper_t* s = (voc_shaper_t*) shaper;
void const* p = TRI_LookupByKeyAssociativeSynced(&s->_attributeIds, &aid);
if (p == nullptr) {
return nullptr;
}
return static_cast<char const*>(p) + sizeof(TRI_df_attribute_marker_t);
return GetAttributeName(p);
}
////////////////////////////////////////////////////////////////////////////////
@ -292,10 +263,11 @@ static char const* LookupAttributeId (TRI_shaper_t* shaper,
static uint64_t HashElementShape (TRI_associative_synced_t* array,
void const* element) {
char const* e = static_cast<char const*>(element);
TRI_shape_t const* ee = static_cast<TRI_shape_t const*>(element);
TRI_shape_t const* shape = static_cast<TRI_shape_t const*>(element);
assert(shape != nullptr);
char const* s = reinterpret_cast<char const*>(shape);
return TRI_FnvHashPointer(e + + sizeof(TRI_shape_sid_t), ee->_size - sizeof(TRI_shape_sid_t));
return TRI_FnvHashPointer(s + sizeof(TRI_shape_sid_t), shape->_size - sizeof(TRI_shape_sid_t));
}
////////////////////////////////////////////////////////////////////////////////
@ -305,16 +277,15 @@ static uint64_t HashElementShape (TRI_associative_synced_t* array,
static bool EqualElementShape (TRI_associative_synced_t* array,
void const* left,
void const* right) {
char const* l = static_cast<char const*>(left);
char const* r = static_cast<char const*>(right);
TRI_shape_t const* l = static_cast<TRI_shape_t const*>(left);
TRI_shape_t const* r = static_cast<TRI_shape_t const*>(right);
char const* ll = reinterpret_cast<char const*>(l);
char const* rr = reinterpret_cast<char const*>(r);
TRI_shape_t const* ll = static_cast<TRI_shape_t const*>(left);
TRI_shape_t const* rr = static_cast<TRI_shape_t const*>(right);
return (ll->_size == rr->_size)
&& memcmp(l + sizeof(TRI_shape_sid_t),
r + sizeof(TRI_shape_sid_t),
ll->_size - sizeof(TRI_shape_sid_t)) == 0;
return (l->_size == r->_size)
&& memcmp(ll + sizeof(TRI_shape_sid_t),
rr + sizeof(TRI_shape_sid_t),
l->_size - sizeof(TRI_shape_sid_t)) == 0;
}
////////////////////////////////////////////////////////////////////////////////
@ -327,30 +298,16 @@ static bool EqualElementShape (TRI_associative_synced_t* array,
static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
TRI_shape_t* shape,
bool create,
bool isLocked) {
char* mem;
TRI_df_marker_t* result;
TRI_df_shape_marker_t* marker;
TRI_doc_datafile_info_t* dfi;
TRI_voc_fid_t fid;
TRI_voc_size_t totalSize;
TRI_shape_t const* found;
TRI_shape_t* l;
int res;
voc_shaper_t* s;
void* f;
bool create) {
voc_shaper_t* s = reinterpret_cast<voc_shaper_t*>(shaper);
TRI_shape_t const* found = TRI_LookupBasicShapeShaper(shape);
s = (voc_shaper_t*) shaper;
found = TRI_LookupBasicShapeShaper(shape);
if (found == NULL) {
if (found == nullptr) {
found = static_cast<TRI_shape_t const*>(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape));
}
// shape found, free argument and return
if (found != NULL) {
if (found != nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape);
return found;
@ -358,94 +315,52 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
// not found
if (! create) {
return 0;
return nullptr;
}
// initialise a new shape marker
totalSize = (TRI_voc_size_t) (sizeof(TRI_df_shape_marker_t) + shape->_size);
mem = (char*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, totalSize, false);
if (mem == NULL) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
marker = (TRI_df_shape_marker_t*) mem;
assert(marker != NULL);
TRI_InitMarker(mem, TRI_DF_MARKER_SHAPE, totalSize);
// copy shape into the marker
memcpy(mem + sizeof(TRI_df_shape_marker_t), shape, shape->_size);
// get next shape id
TRI_shape_sid_t const sid = s->_nextSid++;
shape->_sid = sid;
TRI_primary_collection_t* primary = &s->_collection->base;
triagens::wal::ShapeMarker marker(primary->base._vocbase->_id, primary->base._info._cid, shape);
TRI_shape_t const* result;
// lock the index and check the element is still missing
TRI_LockMutex(&s->_shapeLock);
{
MUTEX_LOCKER(s->_shapeLock);
found = static_cast<TRI_shape_t const*>(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape));
found = static_cast<TRI_shape_t const*>(TRI_LookupByElementAssociativeSynced(&s->_shapeDictionary, shape));
if (found != 0) {
TRI_UnlockMutex(&s->_shapeLock);
if (found != nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
return found;
}
// get next shape number and write into marker
((TRI_shape_t*) (mem + sizeof(TRI_df_shape_marker_t)))->_sid = s->_nextSid++;
if (! isLocked) {
// write-lock
s->_collection->base.beginWrite(&s->_collection->base);
}
// write shape into the collection
res = TRI_WriteMarkerDocumentCollection(s->_collection, &marker->base, totalSize, &fid, &result, false);
if (! isLocked) {
// write-unlock
s->_collection->base.endWrite(&s->_collection->base);
}
if (res != TRI_ERROR_NO_ERROR) {
TRI_UnlockMutex(&s->_shapeLock);
LOG_ERROR("an error occurred while writing shape data into shapes collection: %s",
TRI_errno_string(res));
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
return NULL;
}
assert(result != NULL);
// update datafile info
dfi = TRI_FindDatafileInfoPrimaryCollection(&s->_collection->base, fid, true);
if (dfi != NULL) {
dfi->_numberShapes++;
dfi->_sizeShapes += (int64_t) TRI_DF_ALIGN_BLOCK(totalSize);
}
return found;
}
// enter into the dictionaries
l = (TRI_shape_t*) (((char*) result) + sizeof(TRI_df_shape_marker_t));
f = TRI_InsertKeyAssociativeSynced(&s->_shapeIds, &l->_sid, l, false);
assert(f == NULL);
// write marker into wal
triagens::wal::SlotInfo slotInfo = triagens::wal::LogfileManager::instance()->writeMarker(marker, false);
if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) {
LOG_WARNING("could not save shape marker in log");
return nullptr;
}
f = TRI_InsertElementAssociativeSynced(&s->_shapeDictionary, l, false);
assert(f == NULL);
char const* m = static_cast<char const*>(slotInfo.mem) + sizeof(triagens::wal::shape_marker_t);
result = reinterpret_cast<TRI_shape_t const*>(m);
void* f = TRI_InsertKeyAssociativeSynced(&s->_shapeIds, &sid, (void*) m, false);
assert(f == nullptr);
f = TRI_InsertElementAssociativeSynced(&s->_shapeDictionary, (void*) m, false);
assert(f == nullptr);
}
TRI_UnlockMutex(&s->_shapeLock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shape);
return l;
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -465,9 +380,10 @@ static uint64_t HashKeyShapeId (TRI_associative_synced_t* array,
static uint64_t HashElementShapeId (TRI_associative_synced_t* array,
void const* element) {
TRI_shape_t const* e = static_cast<TRI_shape_t const*>(element);
TRI_shape_t const* shape = static_cast<TRI_shape_t const*>(element);
assert(shape != nullptr);
return TRI_FnvHashPointer(&e->_sid, sizeof(TRI_shape_sid_t));
return TRI_FnvHashPointer(&shape->_sid, sizeof(TRI_shape_sid_t));
}
////////////////////////////////////////////////////////////////////////////////
@ -478,9 +394,10 @@ static bool EqualKeyShapeId (TRI_associative_synced_t* array,
void const* key,
void const* element) {
TRI_shape_sid_t const* k = static_cast<TRI_shape_sid_t const*>(key);
TRI_shape_t const* e = static_cast<TRI_shape_t const*>(element);
TRI_shape_t const* shape = static_cast<TRI_shape_t const*>(element);
assert(shape != nullptr);
return *k == e->_sid;
return *k == shape->_sid;
}
////////////////////////////////////////////////////////////////////////////////
@ -491,7 +408,7 @@ static TRI_shape_t const* LookupShapeId (TRI_shaper_t* shaper,
TRI_shape_sid_t sid) {
TRI_shape_t const* shape = TRI_LookupSidBasicShapeShaper(sid);
if (shape == NULL) {
if (shape == nullptr) {
voc_shaper_t* s = (voc_shaper_t*) shaper;
shape = static_cast<TRI_shape_t const*>(TRI_LookupByKeyAssociativeSynced(&s->_shapeIds, &sid));
}
@ -624,10 +541,6 @@ static int InitStep1VocShaper (voc_shaper_t* shaper) {
////////////////////////////////////////////////////////////////////////////////
static int InitStep2VocShaper (voc_shaper_t* shaper) {
TRI_InitMutex(&shaper->_shapeLock);
TRI_InitMutex(&shaper->_attributeLock);
TRI_InitMutex(&shaper->_accessorLock);
shaper->_nextAid = 1; // id of next attribute to hand out
shaper->_nextSid = TRI_FirstCustomShapeIdShaper(); // id of next shape to hand out
@ -644,37 +557,32 @@ static int InitStep2VocShaper (voc_shaper_t* shaper) {
TRI_shaper_t* TRI_CreateVocShaper (TRI_vocbase_t* vocbase,
TRI_document_collection_t* document) {
voc_shaper_t* shaper = static_cast<voc_shaper_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(voc_shaper_t), false));
if (shaper == NULL) {
// out of memory
return NULL;
}
voc_shaper_t* shaper = new voc_shaper_t;
shaper->_collection = document;
int res = TRI_InitShaper(&shaper->base, TRI_UNKNOWN_MEM_ZONE);
if (res != TRI_ERROR_NO_ERROR) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shaper);
delete shaper;
return NULL;
return nullptr;
}
res = InitStep1VocShaper(shaper);
if (res != TRI_ERROR_NO_ERROR) {
TRI_FreeShaper(&shaper->base);
delete shaper;
return NULL;
return nullptr;
}
res = InitStep2VocShaper(shaper);
if (res != TRI_ERROR_NO_ERROR) {
TRI_FreeVocShaper(&shaper->base);
delete shaper;
return NULL;
return nullptr;
}
// and return
@ -688,7 +596,7 @@ TRI_shaper_t* TRI_CreateVocShaper (TRI_vocbase_t* vocbase,
void TRI_DestroyVocShaper (TRI_shaper_t* s) {
voc_shaper_t* shaper = (voc_shaper_t*) s;
assert(shaper != NULL);
assert(shaper != nullptr);
TRI_DestroyAssociativeSynced(&shaper->_attributeNames);
TRI_DestroyAssociativeSynced(&shaper->_attributeIds);
@ -698,15 +606,11 @@ void TRI_DestroyVocShaper (TRI_shaper_t* s) {
for (size_t i = 0; i < shaper->_accessors._nrAlloc; ++i) {
TRI_shape_access_t* accessor = (TRI_shape_access_t*) shaper->_accessors._table[i];
if (accessor != NULL) {
if (accessor != nullptr) {
TRI_FreeShapeAccessor(accessor);
}
}
TRI_DestroyAssociativePointer(&shaper->_accessors);
TRI_DestroyMutex(&shaper->_shapeLock);
TRI_DestroyMutex(&shaper->_attributeLock);
TRI_DestroyShaper(s);
}
@ -716,7 +620,8 @@ void TRI_DestroyVocShaper (TRI_shaper_t* s) {
void TRI_FreeVocShaper (TRI_shaper_t* shaper) {
TRI_DestroyVocShaper(shaper);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shaper);
delete shaper;
}
// -----------------------------------------------------------------------------
@ -743,41 +648,35 @@ int TRI_MoveMarkerVocShaper (TRI_shaper_t* s,
if (marker->_type == TRI_DF_MARKER_SHAPE) {
char* p = ((char*) marker) + sizeof(TRI_df_shape_marker_t);
TRI_shape_t* l = (TRI_shape_t*) p;
void* f;
TRI_LockMutex(&shaper->_shapeLock);
MUTEX_LOCKER(shaper->_shapeLock);
// remove the old marker
// and re-insert the marker with the new pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_shapeIds, &l->_sid, l, true);
assert(f != NULL);
void* f = TRI_InsertKeyAssociativeSynced(&shaper->_shapeIds, &l->_sid, l, true);
assert(f != nullptr);
// same for the shape dictionary
// delete and re-insert
f = TRI_InsertElementAssociativeSynced(&shaper->_shapeDictionary, l, true);
assert(f != NULL);
TRI_UnlockMutex(&shaper->_shapeLock);
assert(f != nullptr);
}
else if (marker->_type == TRI_DF_MARKER_ATTRIBUTE) {
TRI_df_attribute_marker_t* m = (TRI_df_attribute_marker_t*) marker;
char* p = ((char*) m) + sizeof(TRI_df_attribute_marker_t);
void* f;
TRI_LockMutex(&shaper->_attributeLock);
MUTEX_LOCKER(shaper->_attributeLock);
// remove attribute by name (p points to new location of name, but names
// are identical in old and new marker)
// and re-insert same attribute with adjusted pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeNames, p, m, true);
assert(f != NULL);
void* f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeNames, p, m, true);
assert(f != nullptr);
// same for attribute ids
// delete and re-insert same attribute with adjusted pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeIds, &m->_aid, m, true);
assert(f != NULL);
TRI_UnlockMutex(&shaper->_attributeLock);
assert(f != nullptr);
}
return TRI_ERROR_NO_ERROR;
@ -789,18 +688,17 @@ int TRI_MoveMarkerVocShaper (TRI_shaper_t* s,
int TRI_InsertShapeVocShaper (TRI_shaper_t* s,
TRI_df_marker_t const* marker) {
voc_shaper_t* shaper = (voc_shaper_t*) s;
char* p = ((char*) marker) + sizeof(TRI_df_shape_marker_t);
TRI_shape_t* l = (TRI_shape_t*) p;
void* f;
LOG_TRACE("found shape %lu", (unsigned long) l->_sid);
f = TRI_InsertElementAssociativeSynced(&shaper->_shapeDictionary, l, false);
assert(f == NULL);
voc_shaper_t* shaper = (voc_shaper_t*) s;
void* f = TRI_InsertElementAssociativeSynced(&shaper->_shapeDictionary, l, false);
assert(f == nullptr);
f = TRI_InsertKeyAssociativeSynced(&shaper->_shapeIds, &l->_sid, l, false);
assert(f == NULL);
assert(f == nullptr);
if (shaper->_nextSid <= l->_sid) {
shaper->_nextSid = l->_sid + 1;
@ -815,16 +713,15 @@ int TRI_InsertShapeVocShaper (TRI_shaper_t* s,
int TRI_InsertAttributeVocShaper (TRI_shaper_t* s,
TRI_df_marker_t const* marker) {
voc_shaper_t* shaper = (voc_shaper_t*) s;
TRI_df_attribute_marker_t* m = (TRI_df_attribute_marker_t*) marker;
char* p = ((char*) m) + sizeof(TRI_df_attribute_marker_t);
void* f;
LOG_TRACE("found attribute '%s', aid: %lu", p, (unsigned long) m->_aid);
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeNames, p, m, false);
voc_shaper_t* shaper = (voc_shaper_t*) s;
void* f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeNames, p, m, false);
if (f != NULL) {
if (f != nullptr) {
char const* name = shaper->_collection->base.base._info._name;
#ifdef TRI_ENABLE_MAINTAINER_MODE
@ -836,7 +733,7 @@ int TRI_InsertAttributeVocShaper (TRI_shaper_t* s,
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeIds, &m->_aid, m, false);
if (f != NULL) {
if (f != nullptr) {
char const* name = shaper->_collection->base.base._info._name;
#ifdef TRI_ENABLE_MAINTAINER_MODE
@ -861,27 +758,25 @@ int TRI_InsertAttributeVocShaper (TRI_shaper_t* s,
TRI_shape_access_t const* TRI_FindAccessorVocShaper (TRI_shaper_t* s,
TRI_shape_sid_t sid,
TRI_shape_pid_t pid) {
voc_shaper_t* shaper = (voc_shaper_t*) s;
TRI_shape_access_t search;
TRI_shape_access_t* accessor;
search._sid = sid;
search._pid = pid;
voc_shaper_t* shaper = (voc_shaper_t*) s;
MUTEX_LOCKER(shaper->_accessorLock);
TRI_LockMutex(&shaper->_accessorLock);
TRI_shape_access_t const* found = static_cast<TRI_shape_access_t const*>(TRI_LookupByElementAssociativePointer(&shaper->_accessors, &search));
if (found == NULL) {
found = accessor = TRI_ShapeAccessor(&shaper->base, sid, pid);
if (found == nullptr) {
found = TRI_ShapeAccessor(&shaper->base, sid, pid);
// TRI_ShapeAccessor can return a NULL pointer
if (found != NULL) {
TRI_InsertElementAssociativePointer(&shaper->_accessors, accessor, true);
if (found != nullptr) {
TRI_InsertElementAssociativePointer(&shaper->_accessors, const_cast<void*>(static_cast<void const*>(found)), true);
}
}
TRI_UnlockMutex(&shaper->_accessorLock);
return found;
}
@ -895,12 +790,9 @@ bool TRI_ExtractShapedJsonVocShaper (TRI_shaper_t* shaper,
TRI_shape_pid_t pid,
TRI_shaped_json_t* result,
TRI_shape_t const** shape) {
TRI_shape_access_t const* accessor;
bool ok;
TRI_shape_access_t const* accessor = TRI_FindAccessorVocShaper(shaper, document->_sid, pid);
accessor = TRI_FindAccessorVocShaper(shaper, document->_sid, pid);
if (accessor == NULL) {
if (accessor == nullptr) {
LOG_TRACE("failed to get accessor for sid %lu and path %lu",
(unsigned long) document->_sid,
(unsigned long) pid);
@ -910,7 +802,7 @@ bool TRI_ExtractShapedJsonVocShaper (TRI_shaper_t* shaper,
*shape = accessor->_shape;
if (accessor->_shape == NULL) {
if (accessor->_shape == nullptr) {
LOG_TRACE("expecting any object for path %lu, got nothing",
(unsigned long) pid);
@ -926,7 +818,7 @@ bool TRI_ExtractShapedJsonVocShaper (TRI_shaper_t* shaper,
return false;
}
ok = TRI_ExecuteShapeAccessor(accessor, document, result);
bool ok = TRI_ExecuteShapeAccessor(accessor, document, result);
if (! ok) {
LOG_TRACE("failed to get accessor for sid %lu and path %lu",
@ -958,7 +850,7 @@ static int AttributeNameComparator (void const* lhs,
attribute_entry_t const* l = static_cast<attribute_entry_t const*>(lhs);
attribute_entry_t const* r = static_cast<attribute_entry_t const*>(rhs);
if (l->_attribute == NULL || r->_attribute == NULL) {
if (l->_attribute == nullptr || r->_attribute == nullptr) {
// error !
return -1;
}
@ -1019,13 +911,13 @@ static int FillAttributesVector (TRI_vector_t* vector,
char const* a = shaper->lookupAttributeId((TRI_shaper_t*) shaper, aids[i]);
if (a == NULL) {
if (a == nullptr) {
return TRI_ERROR_INTERNAL;
}
char* copy = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, a);
if (copy == NULL) {
if (copy == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
}
@ -1044,13 +936,13 @@ static int FillAttributesVector (TRI_vector_t* vector,
char const* a = shaper->lookupAttributeId((TRI_shaper_t*) shaper, aids[i + fixedEntries]);
if (a == NULL) {
if (a == nullptr) {
return TRI_ERROR_INTERNAL;
}
char* copy = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, a);
if (copy == NULL) {
if (copy == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY;
}
@ -1078,7 +970,7 @@ static void DestroyAttributesVector (TRI_vector_t* vector) {
for (size_t i = 0; i < n; ++i) {
attribute_entry_t* entry = static_cast<attribute_entry_t*>(TRI_AtVector(vector, i));
if (entry->_attribute != NULL) {
if (entry->_attribute != nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, entry->_attribute);
}
}
@ -1114,7 +1006,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
int result;
// left is either a shaped json or a shaped sub object
if (leftDocument != NULL) {
if (leftDocument != nullptr) {
ptr = (char const*) leftDocument->_data;
left._sid = leftObject->_sid;
@ -1126,7 +1018,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
}
// right is either a shaped json or a shaped sub object
if (rightDocument != NULL) {
if (rightDocument != nullptr) {
ptr = (char const*) rightDocument->_data;
right._sid = rightObject->_sid;
@ -1148,7 +1040,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
rightShape = rightShaper->lookupShapeId(rightShaper, right._sid);
}
if (leftShape == NULL || rightShape == NULL) {
if (leftShape == nullptr || rightShape == nullptr) {
LOG_ERROR("shape not found");
assert(false);
}
@ -1392,11 +1284,11 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
&rightElement);
}
result = TRI_CompareShapeTypes(NULL,
NULL,
result = TRI_CompareShapeTypes(nullptr,
nullptr,
&leftElement,
NULL,
NULL,
nullptr,
nullptr,
&rightElement,
leftShaper,
rightShaper);
@ -1479,11 +1371,11 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
break;
}
result = TRI_CompareShapeTypes(NULL,
NULL,
result = TRI_CompareShapeTypes(nullptr,
nullptr,
&l->_value,
NULL,
NULL,
nullptr,
nullptr,
&r->_value,
leftShaper,
rightShaper);

View File

@ -94,6 +94,15 @@ Marker::~Marker () {
/// @brief store a null-terminated string and length inside the marker
////////////////////////////////////////////////////////////////////////////////
void Marker::storeSizedString (size_t offset,
std::string const& value) {
return storeSizedString(offset, value.c_str(), value.size());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief store a null-terminated string and length inside the marker
////////////////////////////////////////////////////////////////////////////////
void Marker::storeSizedString (size_t offset,
char const* value,
size_t length) {
@ -105,6 +114,72 @@ void Marker::storeSizedString (size_t offset,
p[length] = '\0';
}
// -----------------------------------------------------------------------------
// --SECTION-- AttributeMarker
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create marker
////////////////////////////////////////////////////////////////////////////////
AttributeMarker::AttributeMarker (TRI_voc_tick_t databaseId,
TRI_voc_cid_t collectionId,
TRI_shape_aid_t attributeId,
std::string const& attributeName)
: Marker(TRI_WAL_MARKER_ATTRIBUTE, sizeof(attribute_marker_t) + alignedSize(attributeName.size() + 1)) {
attribute_marker_t* m = reinterpret_cast<attribute_marker_t*>(begin());
m->_databaseId = databaseId;
m->_collectionId = collectionId;
m->_attributeId = attributeId;
storeSizedString(sizeof(attribute_marker_t), attributeName);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy marker
////////////////////////////////////////////////////////////////////////////////
AttributeMarker::~AttributeMarker () {
}
// -----------------------------------------------------------------------------
// --SECTION-- ShapeMarker
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create marker
////////////////////////////////////////////////////////////////////////////////
ShapeMarker::ShapeMarker (TRI_voc_tick_t databaseId,
TRI_voc_cid_t collectionId,
TRI_shape_t const* shape)
: Marker(TRI_WAL_MARKER_SHAPE, sizeof(shape_marker_t) + shape->_size) {
shape_marker_t* m = reinterpret_cast<shape_marker_t*>(begin());
m->_databaseId = databaseId;
m->_collectionId = collectionId;
memcpy(this->shape(), shape, shape->_size);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy marker
////////////////////////////////////////////////////////////////////////////////
ShapeMarker::~ShapeMarker () {
}
// -----------------------------------------------------------------------------
// --SECTION-- BeginTransactionMarker
// -----------------------------------------------------------------------------
@ -119,8 +194,7 @@ void Marker::storeSizedString (size_t offset,
BeginTransactionMarker::BeginTransactionMarker (TRI_voc_tick_t databaseId,
TRI_voc_tid_t transactionId)
: Marker(TRI_WAL_MARKER_BEGIN_TRANSACTION,
sizeof(transaction_begin_marker_t)) {
: Marker(TRI_WAL_MARKER_BEGIN_TRANSACTION, sizeof(transaction_begin_marker_t)) {
transaction_begin_marker_t* m = reinterpret_cast<transaction_begin_marker_t*>(begin());
@ -149,8 +223,7 @@ BeginTransactionMarker::~BeginTransactionMarker () {
CommitTransactionMarker::CommitTransactionMarker (TRI_voc_tick_t databaseId,
TRI_voc_tid_t transactionId)
: Marker(TRI_WAL_MARKER_COMMIT_TRANSACTION,
sizeof(transaction_commit_marker_t)) {
: Marker(TRI_WAL_MARKER_COMMIT_TRANSACTION, sizeof(transaction_commit_marker_t)) {
transaction_commit_marker_t* m = reinterpret_cast<transaction_commit_marker_t*>(begin());
@ -179,8 +252,7 @@ CommitTransactionMarker::~CommitTransactionMarker () {
AbortTransactionMarker::AbortTransactionMarker (TRI_voc_tick_t databaseId,
TRI_voc_tid_t transactionId)
: Marker(TRI_WAL_MARKER_ABORT_TRANSACTION,
sizeof(transaction_abort_marker_t)) {
: Marker(TRI_WAL_MARKER_ABORT_TRANSACTION, sizeof(transaction_abort_marker_t)) {
transaction_abort_marker_t* m = reinterpret_cast<transaction_abort_marker_t*>(begin());
@ -226,7 +298,7 @@ DocumentMarker::DocumentMarker (TRI_voc_tick_t databaseId,
m->_offsetLegend = m->_offsetKey + alignedSize(key.size() + 1);
m->_offsetJson = m->_offsetLegend + alignedSize(legend.getSize());
storeSizedString(m->_offsetKey, key.c_str(), key.size());
storeSizedString(m->_offsetKey, key);
// store legend
{
@ -356,7 +428,7 @@ EdgeMarker::EdgeMarker (TRI_voc_tick_t databaseId,
m->_offsetJson = m->_offsetLegend + alignedSize(legend.getSize());
// store keys
storeSizedString(m->_offsetKey, key.c_str(), key.size());
storeSizedString(m->_offsetKey, key.c_str());
storeSizedString(m->_offsetFromKey, edge->_fromKey, strlen(edge->_fromKey));
storeSizedString(m->_offsetToKey, edge->_toKey, strlen(edge->_toKey));
@ -486,15 +558,14 @@ RemoveMarker::RemoveMarker (TRI_voc_tick_t databaseId,
TRI_voc_rid_t revisionId,
TRI_voc_tid_t transactionId,
std::string const& key)
: Marker(TRI_WAL_MARKER_REMOVE,
sizeof(remove_marker_t) + alignedSize(key.size() + 1)) {
: Marker(TRI_WAL_MARKER_REMOVE, sizeof(remove_marker_t) + alignedSize(key.size() + 1)) {
remove_marker_t* m = reinterpret_cast<remove_marker_t*>(begin());
m->_databaseId = databaseId;
m->_collectionId = collectionId;
m->_rid = revisionId;
m->_tid = transactionId;
storeSizedString(sizeof(remove_marker_t), key.c_str(), key.size());
storeSizedString(sizeof(remove_marker_t), key);
dump();
}

View File

@ -52,8 +52,7 @@ namespace triagens {
TRI_voc_tick_t _databaseId;
TRI_voc_cid_t _collectionId;
TRI_shape_aid_t _aid;
TRI_shape_size_t _size;
TRI_shape_aid_t _attributeId;
};
////////////////////////////////////////////////////////////////////////////////
@ -217,6 +216,9 @@ namespace triagens {
// -----------------------------------------------------------------------------
protected:
void storeSizedString (size_t,
std::string const&);
void storeSizedString (size_t,
char const*,
@ -232,6 +234,50 @@ namespace triagens {
uint32_t const _size;
};
// -----------------------------------------------------------------------------
// --SECTION-- AttributeMarker
// -----------------------------------------------------------------------------
class AttributeMarker : public Marker {
public:
AttributeMarker (TRI_voc_tick_t,
TRI_voc_cid_t,
TRI_shape_aid_t,
std::string const&);
~AttributeMarker ();
public:
inline char* attributeName () const {
// pointer to attribute name
return begin() + sizeof(attribute_marker_t);
}
};
// -----------------------------------------------------------------------------
// --SECTION-- ShapeMarker
// -----------------------------------------------------------------------------
class ShapeMarker : public Marker {
public:
ShapeMarker (TRI_voc_tick_t,
TRI_voc_cid_t,
TRI_shape_t const*);
~ShapeMarker ();
public:
inline char* shape () const {
return begin() + sizeof(shape_marker_t);
}
};
// -----------------------------------------------------------------------------
// --SECTION-- BeginTransactionMarker
// -----------------------------------------------------------------------------
@ -304,7 +350,7 @@ namespace triagens {
return m->_tid;
}
inline char const* key () const {
inline char* key () const {
// pointer to key
return begin() + sizeof(document_marker_t);
}

View File

@ -1110,13 +1110,27 @@ ArangoCollection.prototype.remove = function (id, overwrite, waitForSync) {
id = id._id;
}
var policy = "";
var params = "";
if (overwrite) {
policy = "?policy=last";
if (typeof overwrite === "object") {
// we assume the caller uses new signature (id, data, options)
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "?policy=last";
}
if (options.hasOwnProperty("waitForSync") ) {
waitForSync = options.waitForSync;
}
} else {
if (overwrite) {
params += "?policy=last";
}
}
var url = this._documenturl(id) + policy;
var url = this._documenturl(id) + params;
url = this._appendSyncParameter(url, waitForSync);
if (rev === null) {
@ -1160,6 +1174,9 @@ ArangoCollection.prototype.replace = function (id, data, overwrite, waitForSync)
var params = "";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
@ -1210,6 +1227,9 @@ ArangoCollection.prototype.update = function (id, data, overwrite, keepNull, wai
var params = "";
if (typeof overwrite === "object") {
if (typeof keepNull !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (! options.hasOwnProperty("keepNull")) {

View File

@ -657,13 +657,27 @@ ArangoDatabase.prototype._remove = function (id, overwrite, waitForSync) {
id = id._id;
}
var policy = "";
var params = "";
if (overwrite) {
policy = "?policy=last";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "?policy=last";
}
if (options.hasOwnProperty("waitForSync") ) {
waitForSync = options.waitForSync;
}
} else {
if (overwrite) {
params += "?policy=last";
}
}
var url = this._documenturl(id) + policy;
var url = this._documenturl(id) + params;
url = this._appendSyncParameter(url, waitForSync);
if (rev === null) {
@ -708,6 +722,9 @@ ArangoDatabase.prototype._replace = function (id, data, overwrite, waitForSync)
var params = "";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
@ -759,6 +776,9 @@ ArangoDatabase.prototype._update = function (id, data, overwrite, keepNull, wait
var params = "";
if (typeof overwrite === "object") {
if (typeof keepNull !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (! options.hasOwnProperty("keepNull")) {

View File

@ -1109,13 +1109,27 @@ ArangoCollection.prototype.remove = function (id, overwrite, waitForSync) {
id = id._id;
}
var policy = "";
var params = "";
if (overwrite) {
policy = "?policy=last";
if (typeof overwrite === "object") {
// we assume the caller uses new signature (id, data, options)
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "?policy=last";
}
if (options.hasOwnProperty("waitForSync") ) {
waitForSync = options.waitForSync;
}
} else {
if (overwrite) {
params += "?policy=last";
}
}
var url = this._documenturl(id) + policy;
var url = this._documenturl(id) + params;
url = this._appendSyncParameter(url, waitForSync);
if (rev === null) {
@ -1159,6 +1173,9 @@ ArangoCollection.prototype.replace = function (id, data, overwrite, waitForSync)
var params = "";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
@ -1209,6 +1226,9 @@ ArangoCollection.prototype.update = function (id, data, overwrite, keepNull, wai
var params = "";
if (typeof overwrite === "object") {
if (typeof keepNull !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (! options.hasOwnProperty("keepNull")) {

View File

@ -656,13 +656,27 @@ ArangoDatabase.prototype._remove = function (id, overwrite, waitForSync) {
id = id._id;
}
var policy = "";
var params = "";
if (overwrite) {
policy = "?policy=last";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "?policy=last";
}
if (options.hasOwnProperty("waitForSync") ) {
waitForSync = options.waitForSync;
}
} else {
if (overwrite) {
params += "?policy=last";
}
}
var url = this._documenturl(id) + policy;
var url = this._documenturl(id) + params;
url = this._appendSyncParameter(url, waitForSync);
if (rev === null) {
@ -707,6 +721,9 @@ ArangoDatabase.prototype._replace = function (id, data, overwrite, waitForSync)
var params = "";
if (typeof overwrite === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
@ -758,6 +775,9 @@ ArangoDatabase.prototype._update = function (id, data, overwrite, keepNull, wait
var params = "";
if (typeof overwrite === "object") {
if (typeof keepNull !== "undefined") {
throw "too many arguments";
}
// we assume the caller uses new signature (id, data, options)
var options = overwrite;
if (! options.hasOwnProperty("keepNull")) {

View File

@ -635,12 +635,11 @@ ArangoCollection.prototype.geo = function(loc, order) {
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude})}
/////////////////////////////////////////////////////////////
///
/// The default will find at most 100 documents near the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted according to
/// the distance, with the nearest document coming first. If there are near
/// documents of equal distance, documents are chosen randomly from this set
/// until the limit is reached. It is possible to change the limit using the
/// @FA{limit} operator.
/// The returned list is sorted according to the distance, with the nearest
/// document to the coordinate (@FA{latitude}, @FA{longitude}) coming first.
/// If there are near documents of equal distance, documents are chosen randomly
/// from this set until the limit is reached. It is possible to change the limit
/// using the @FA{limit} operator.
///
/// In order to use the @FN{near} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates
@ -692,8 +691,9 @@ ArangoCollection.prototype.near = function (lat, lon) {
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})}
////////////////////////////////////////////////////////////////////////////
///
/// This will find all documents with in a given radius around the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted by distance.
/// This will find all documents within a given radius around the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted by distance,
/// beginning with the nearest document.
///
/// In order to use the @FN{within} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates

View File

@ -195,20 +195,52 @@ AQLGenerator.prototype._createCursor = function() {
}
};
AQLGenerator.prototype.edges = function(startVertex, direction) {
AQLGenerator.prototype.edges = function(startVertexExample, options) {
this._clearCursor();
var edgeName = "edges_" + this.stack.length;
var query = "FOR " + edgeName
+ " IN GRAPH_EDGES(@graphName,@startVertex_"
+ this.stack.length + ',"'
+ direction + '")';
this.bindVars["startVertex_" + this.stack.length] = startVertex;
var resultName = "edges_" + this.stack.length;
var query = "FOR " + resultName
+ " IN GRAPH_EDGES(@graphName,@startVertexExample_"
+ this.stack.length + ',@options_'
+ this.stack.length + ')';
this.bindVars["startVertexExample_" + this.stack.length] = startVertexExample;
this.bindVars["options_" + this.stack.length] = options;
var stmt = new AQLStatement(query, true);
this.stack.push(stmt);
this.lastEdgeVar = edgeName;
this.lastEdgeVar = resultName;
return this;
};
AQLGenerator.prototype.vertices = function(startEdgeExample, options) {
this._clearCursor();
var resultName = "vertex_" + this.stack.length;
var query = "FOR " + resultName
+ " IN GRAPH_EDGES(@graphName,@startVertexExample_"
+ this.stack.length + ',@options_'
+ this.stack.length + ')';
this.bindVars["startVertexExample_" + this.stack.length] = startEdgeExample;
this.bindVars["options_" + this.stack.length] = options;
var stmt = new AQLStatement(query, true);
this.stack.push(stmt);
this.lastEdgeVar = resultName;
return this;
};
AQLGenerator.prototype.neighbors = function(startVertexExample, options) {
var resultName = "neighbors_" + this.stack.length + ".vertices";
var query = "FOR " + resultName
+ " IN GRAPH_NEIGHBORS(@graphName,@startVertexExample_"
+ this.stack.length + ',@options_'
+ this.stack.length + ')';
this.bindVars["startVertexExample_" + this.stack.length] = startVertexExample;
this.bindVars["options_" + this.stack.length] = options;
var stmt = new AQLStatement(query, true);
this.stack.push(stmt);
this.lastEdgeVar = resultName;
return this;
};
AQLGenerator.prototype.getLastEdgeVar = function() {
if (this.lastEdgeVar === "") {
return false;
@ -415,20 +447,22 @@ var _edgeDefinitions = function () {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief extend an edge definitions
/// @brief extend a list of edge definitions
////////////////////////////////////////////////////////////////////////////////
var _extendEdgeDefinitions = function () {
var _extendEdgeDefinitions = function (edgeDefinition) {
var args = arguments;
var res = args[0];
args = args.slice(1);
res.concat(args);
var args = arguments, i = 0;
Object.keys(args).forEach(function (x) {
i++;
if (i === 1) {return;}
edgeDefinition.push(args[x]);
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new graph
////////////////////////////////////////////////////////////////////////////////
@ -471,7 +505,6 @@ var _create = function (graphName, edgeDefinitions) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor.
////////////////////////////////////////////////////////////////////////////////
@ -487,13 +520,31 @@ var Graph = function(graphName, edgeDefinitions, vertexCollections, edgeCollecti
var wrap = wrapCollection(obj);
var old_remove = wrap.remove;
wrap.remove = function(vertexId, options) {
var myEdges = self._EDGES(vertexId);
myEdges.forEach(
function(edgeObj) {
var edgeId = edgeObj._id;
var edgeCollection = edgeId.split("/")[0];
if (db[edgeCollection] && db[edgeCollection].exists(edgeId)) {
db[edgeCollection].remove(edgeId);
var graphs = getGraphCollection().toArray();
var vertexCollectionName = vertexId.split("/")[0];
graphs.forEach(
function(graph) {
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
if (from.indexOf(vertexCollectionName) !== -1
|| to.indexOf(vertexCollectionName) !== -1
) {
var edges = db._collection(collection).toArray();
edges.forEach(
function(edge) {
if (edge._from === vertexId || edge._to === vertexId) {
db._remove(edge._id);
}
}
);
}
}
);
}
}
);
@ -503,6 +554,7 @@ var Graph = function(graphName, edgeDefinitions, vertexCollections, edgeCollecti
}
return old_remove(vertexId, options);
};
self[key] = wrap;
});
@ -581,9 +633,10 @@ var checkIfMayBeDropped = function(colName, graphName, graphs) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
if (collection === colName ||
from.indexOf(colName) !== -1 ||
to.indexOf(colName) !== -1) {
if (collection === colName
|| from.indexOf(colName) !== -1
|| to.indexOf(colName) !== -1
) {
result = false;
}
}
@ -712,30 +765,41 @@ Graph.prototype._OUTEDGES = function(vertexId) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief _edges(vertexId).
/// @brief _edges(vertexExample).
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._edges = function(vertexId) {
Graph.prototype._edges = function(vertexExample) {
var AQLStmt = new AQLGenerator(this);
return AQLStmt.edges(vertexId, "any");
return AQLStmt.edges(vertexExample, {direction : "any"});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief _vertices(edgeExample).
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._vertices = function(edgeExample) {
var AQLStmt = new AQLGenerator(this);
return AQLStmt.vertices(edgeExample, {direction : "any"});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief _inEdges(vertexId).
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._inEdges = function(vertexId) {
Graph.prototype._inEdges = function(vertexExample) {
var AQLStmt = new AQLGenerator(this);
return AQLStmt.edges(vertexId, "inbound");
return AQLStmt.edges(vertexExample, {direction : "inbound"});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief _outEdges(vertexId).
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._outEdges = function(vertexId) {
Graph.prototype._outEdges = function(vertexExample) {
var AQLStmt = new AQLGenerator(this);
return AQLStmt.edges(vertexId, "outbound");
return AQLStmt.edges(vertexExample, {direction : "outbound"});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get ingoing vertex of an edge.
@ -788,6 +852,60 @@ Graph.prototype._getVertexCollectionByName = function(name) {
throw "Collection " + name + " does not exist in graph.";
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get neighbors of a vertex in the graph.
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._neighbors = function(vertexExample, options) {
var current_vertex,
target_array = [],
addNeighborToList,
AQLStmt;
if (! options) {
options = { };
}
AQLStmt = new AQLGenerator(this);
return AQLStmt.neighbors(vertexExample, options);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get common neighbors of two vertices in the graph.
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._listCommonNeighbors = function(vertex1, vertex2, options) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get amount of common neighbors of two vertices in the graph.
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._amountCommonNeighbors = function(vertex1, vertex2, options) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get common properties of two vertices in the graph.
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._listCommonProperties = function(vertex1, vertex2, options) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get amount of common properties of two vertices in the graph.
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._amountCommonProperties = function(vertex1, vertex2, options) {
};
// -----------------------------------------------------------------------------
// --SECTION-- MODULE EXPORTS
// -----------------------------------------------------------------------------

View File

@ -1082,6 +1082,37 @@ function CollectionDocumentSuite () {
var a4 = collection.remove(a1, true);
assertEqual(a4, false);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a document using new signature
////////////////////////////////////////////////////////////////////////////////
testDeleteWithNewSignatureDocument : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.replace(a1, { a : 2 });
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
try {
collection.remove(a1);
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_CONFLICT.code, err.errorNum);
}
var a3 = collection.remove(a1, {"overwrite": true});
assertEqual(a3, true);
var a4 = collection.remove(a1, {"overwrite": true});
assertEqual(a4, false);
},
@ -1094,8 +1125,23 @@ function CollectionDocumentSuite () {
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
//document, data, overwrite, keepNull, waitForSync
var a2 = collection.update(a1, { a : 2 }, true, true, false);
var a2 = collection.update(a1, { a : 2 }, true, false);
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief update a document, waitForSync=false; using new signature
////////////////////////////////////////////////////////////////////////////////
testUpdateWithNewSignatureDocumentSyncFalse : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.update(a1, { a : 2 }, {"overwrite": true, "waitForSync" : false});
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
@ -1111,7 +1157,23 @@ function CollectionDocumentSuite () {
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.update(a1, { a : 2 }, true, true);
//document, data, overwrite, keepNull, waitForSync
var a2 = collection.update(a1, { a : 2 }, true, true, true);
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief update a document, waitForSync=true,new signature
////////////////////////////////////////////////////////////////////////////////
testUpdateWithNewSignatureDocumentSyncTrue : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.update(a1, { a : 2 }, {"overwrite": true, "waitForSync" : true});
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
@ -1130,6 +1192,19 @@ function CollectionDocumentSuite () {
var a2 = collection.remove(a1, true, false);
assertEqual(a2, true);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a document, waitForSync=false , using new signature
////////////////////////////////////////////////////////////////////////////////
testDeleteWithNewSignatureDocumentSyncFalse : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.remove(a1, {"overwrite": true, "waitForSync": false});
assertEqual(a2, true);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a document, waitForSync=true
@ -1144,6 +1219,19 @@ function CollectionDocumentSuite () {
var a2 = collection.remove(a1, true, true);
assertEqual(a2, true);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a document, waitForSync=true , using new signature
////////////////////////////////////////////////////////////////////////////////
testDeleteWithNewSignatureDocumentSyncTrue : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = collection.remove(a1, {"overwrite": true, "waitForSync": true});
assertEqual(a2, true);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a deleted document
@ -1784,11 +1872,43 @@ function DatabaseDocumentSuite () {
assertEqual(ERRORS.ERROR_ARANGO_CONFLICT.code, err.errorNum);
}
var a3 = db._remove(a1, true);
var a3 = db._remove(a1, {"overwrite" : true});
assertEqual(a3, true);
var a4 = db._remove(a1, true);
var a4 = db._remove(a1, {"overwrite" : true});
assertEqual(a4, false);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief delete a document using new signature of the remove function
/// of the remove function
////////////////////////////////////////////////////////////////////////////////
testDeleteWithNewSignatureDocument : function () {
var a1 = collection.save({ a : 1});
assertTypeOf("string", a1._id);
assertTypeOf("string", a1._rev);
var a2 = db._replace(a1, { a : 2 });
assertEqual(a1._id, a2._id);
assertNotEqual(a1._rev, a2._rev);
try {
db._remove(a1);
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_CONFLICT.code, err.errorNum);
}
var a3 = db._remove(a1, {"overwrite" : true});
assertEqual(a3, true);
var a4 = db._remove(a1, {"overwrite" : true});
assertEqual(a4, false);
},

View File

@ -203,6 +203,40 @@ function GeneralGraphCreationSuite() {
]);
},
testExtendEdgeDefinitions : function () {
//with empty args
assertEqual(graph._edgeDefinitions(), []);
//with args
var ed =graph._edgeDefinitions(
graph._undirectedRelationDefinition("relationName", "vertexC1"),
graph._directedRelationDefinition("relationName",
["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"])
);
graph._extendEdgeDefinitions(ed, graph._undirectedRelationDefinition("relationName", "vertexC1"));
assertEqual(ed, [
{
collection: "relationName",
from: ["vertexC1"],
to: ["vertexC1"]
},
{
collection: "relationName",
from: ["vertexC1", "vertexC2"],
to: ["vertexC3", "vertexC4"]
},
{
collection: "relationName",
from: ["vertexC1"],
to: ["vertexC1"]
}
]);
},
test_create : function () {
if (db._collection("_graphs").exists(gn)) {
db._collection("_graphs").remove(gn);
@ -267,7 +301,12 @@ function GeneralGraphCreationSuite() {
try {
graph._create(
"",
edgeDef
graph._edgeDefinitions(
graph._undirectedRelationDefinition("relationName", "vertexC1"),
graph._directedRelationDefinition("relationName2",
["vertexC1", "vertexC2"], ["vertexC3", "vertexC4"]
)
)
);
fail();
} catch (err) {
@ -474,10 +513,10 @@ function GeneralGraphAQLQueriesSuite() {
test_edges: function() {
var query = g._edges(v1 + "/1");
assertEqual(query.printQuery(), 'FOR edges_0 IN GRAPH_EDGES('
+ '@graphName,@startVertex_0,"any")');
+ '@graphName,@startVertexExample_0,@options_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
var result = query.toArray();
assertEqual(result.length, 3);
assertTrue(findIdInResult(result, e1), "Did not include e1");
@ -492,10 +531,10 @@ function GeneralGraphAQLQueriesSuite() {
test_outEdges: function() {
var query = g._outEdges(v1 + "/1");
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"outbound")');
+ '@graphName,@startVertexExample_0,@options_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
var result = query.toArray();
assertEqual(result.length, 2);
assertTrue(findIdInResult(result, e1), "Did not include e1");
@ -510,10 +549,10 @@ function GeneralGraphAQLQueriesSuite() {
test_inEdges: function() {
var query = g._inEdges(v1 + "/1");
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"inbound")');
+ '@graphName,@startVertexExample_0,@options_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
var result = query.toArray();
assertEqual(result.length, 1);
assertTrue(findIdInResult(result, e2), "Did not include e2");
@ -521,13 +560,13 @@ function GeneralGraphAQLQueriesSuite() {
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
test_restrictOnEdges: function() {
/*test_restrictOnEdges: function() {
var query = g._edges(v1 + "/1").restrict(included);
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"any",{},@restrictions_0)');
+ '@graphName,@startVertexExample_0,@options_0,{},@restrictions_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
assertEqual(bindVars.restrictions_0, [included]);
var result = query.toArray();
@ -535,19 +574,19 @@ function GeneralGraphAQLQueriesSuite() {
assertTrue(findIdInResult(result, e1), "Did not include e1");
assertTrue(findIdInResult(result, e2), "Did not include e2");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
},*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: restrict construct on inEdges
////////////////////////////////////////////////////////////////////////////////
test_restrictOnInEdges: function() {
/* test_restrictOnInEdges: function() {
var query = g._inEdges(v1 + "/1").restrict(included);
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"inbound",{},@restrictions_0)');
+ '@graphName,@startVertexExample_0,@options_0,{},@restrictions_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
assertEqual(bindVars.restrictions_0, [included]);
var result = query.toArray();
assertEqual(result.length, 1);
@ -555,25 +594,25 @@ function GeneralGraphAQLQueriesSuite() {
assertFalse(findIdInResult(result, e1), "e1 is not excluded");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: restrict construct on outEdges
////////////////////////////////////////////////////////////////////////////////
test_restrictOnOutEdges: function() {
/* test_restrictOnOutEdges: function() {
var query = g._outEdges(v1 + "/1").restrict(included);
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"outbound",{},@restrictions_0)');
+ '@graphName,@startVertexExample_0,@options_0,{},@restrictions_0)');
var bindVars = query.bindVars;
assertEqual(bindVars.graphName, graphName);
assertEqual(bindVars.startVertex_0, v1 + "/1");
assertEqual(bindVars.startVertexExample_0, v1 + "/1");
assertEqual(bindVars.restrictions_0, [included]);
var result = query.toArray();
assertEqual(result.length, 1);
assertTrue(findIdInResult(result, e1), "Did not include e1");
assertFalse(findIdInResult(result, e2), "e2 is not excluded");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
},*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: restrict error handling
@ -608,7 +647,7 @@ function GeneralGraphAQLQueriesSuite() {
/// @brief test: filter construct on Edges
////////////////////////////////////////////////////////////////////////////////
test_filterOnEdges: function() {
/* test_filterOnEdges: function() {
var query = g._edges(v1 + "/1").filter({val: true});
// var query = g._edges("v1/1").filter("e.val = true");
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
@ -622,13 +661,13 @@ function GeneralGraphAQLQueriesSuite() {
assertTrue(findIdInResult(result, e1), "Did not include e1");
assertFalse(findIdInResult(result, e2), "e2 is not excluded");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
},*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: filter construct on InEdges
////////////////////////////////////////////////////////////////////////////////
test_filterOnInEdges: function() {
/* test_filterOnInEdges: function() {
var query = g._inEdges(v1 + "/1").filter({val: true});
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"inbound") '
@ -641,13 +680,13 @@ function GeneralGraphAQLQueriesSuite() {
assertFalse(findIdInResult(result, e1), "e1 is not excluded");
assertFalse(findIdInResult(result, e2), "e2 is not excluded");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
},*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: filter construct on OutEdges
////////////////////////////////////////////////////////////////////////////////
test_filterOnOutEdges: function() {
/*test_filterOnOutEdges: function() {
var query = g._outEdges(v1 + "/1").filter({val: true});
assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES("
+ '@graphName,@startVertex_0,"outbound") '
@ -661,7 +700,7 @@ function GeneralGraphAQLQueriesSuite() {
assertFalse(findIdInResult(result, e2), "e2 is not excluded");
assertFalse(findIdInResult(result, e3), "e3 is not excluded");
},
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test: counting of query results
////////////////////////////////////////////////////////////////////////////////
@ -673,7 +712,6 @@ function GeneralGraphAQLQueriesSuite() {
query = g._outEdges(v1 + "/1").filter({val: true});
assertEqual(query.count(), 1);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: Cursor iteration
////////////////////////////////////////////////////////////////////////////////
@ -1056,6 +1094,12 @@ function EdgesAndVerticesSuite() {
assertEqual(result._id, ids.vId12);
result = g._getOutVertex(ids.eId25);
assertEqual(result._id, ids.vId35);
},
test_neighbors : function() {
var ids = fillCollections();
var result = g._neighbors(ids.vId11);
require("internal").print(result);
}
};
@ -1069,9 +1113,10 @@ function EdgesAndVerticesSuite() {
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////
jsunity.run(GeneralGraphAQLQueriesSuite);
jsunity.run(EdgesAndVerticesSuite);
jsunity.run(GeneralGraphCreationSuite);
jsunity.run(GeneralGraphAQLQueriesSuite);
return jsunity.done();

View File

@ -4242,6 +4242,17 @@ function TRAVERSAL_VISITOR (config, result, vertex, path) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for neighbors
////////////////////////////////////////////////////////////////////////////////
function TRAVERSAL_NEIGHBOR_VISITOR (config, result, vertex, path) {
"use strict";
result.push(CLONE({ vertex: vertex, edge: path.edges[0] }));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for tree traversal
////////////////////////////////////////////////////////////////////////////////
@ -4440,7 +4451,6 @@ function TRAVERSAL_FUNC (func,
}
var result = [ ];
if (v !== null) {
var traverser = new TRAVERSAL.Traverser(config);
traverser.traverse(result, v, e);
@ -4687,86 +4697,6 @@ function GRAPH_EDGES (edgeCollection,
return FILTER(result, examples);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected edges
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_EDGES (
graphname, startvertex, direction, edgeexamples, collectionRestrictions) {
"use strict";
// check graph exists and load edgeDefintions
var graph = DOCUMENT_HANDLE("_graphs/" + graphname);
if (!graph) {
THROW(INTERNAL.errors.ERROR_GRAPH_INVALID_GRAPH, "GRAPH_EDGES");
}
// check startvertex exists and parse identifier
var start = DOCUMENT_HANDLE(startvertex);
if (!start) {
THROW(INTERNAL.errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND, "GRAPH_EDGES");
}
var startCollection = startvertex.split("/")[0];
var edgeCollections = [], func;
// validate direction and create edgeCollection array.
if (direction === "outbound") {
func = "outEdges";
graph.edgeDefinitions.forEach(function (def) {
if (def.from.indexOf(startCollection) !== -1 &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else if (direction === "inbound") {
func = "inEdges";
graph.edgeDefinitions.forEach(function (def) {
if (def.to.indexOf(startCollection) !== -1 &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else if (direction === "any") {
func = "edges";
graph.edgeDefinitions.forEach(function (def) {
if ((def.from.indexOf(startCollection) !== -1 ||
def.to.indexOf(startCollection) !== -1) &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_EDGES");
}
if (collectionRestrictions) {
if (typeof collectionRestrictions === "string") {
collectionRestrictions = [collectionRestrictions];
}
if (Array.isArray(collectionRestrictions)) {
edgeCollections = edgeCollections.filter(function (element) {
return collectionRestrictions.indexOf(element) !== -1;
});
}
}
// Now get the result.
var result = [];
edgeCollections.forEach(function (c) {
c = COLLECTION(c);
result = result.concat(c[func](startvertex));
});
return FILTER(result, edgeexamples);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to filter edges based on examples
////////////////////////////////////////////////////////////////////////////////
@ -4823,21 +4753,176 @@ function GRAPH_NEIGHBORS (vertexCollection,
return FILTERED_EDGES(edges, vertex, direction, examples);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief CHECK IF RESTRICTION LIST MATCHES
////////////////////////////////////////////////////////////////////////////////
function FILTER_RESTRICTION (list, restrictionList) {
if (!restrictionList) {
return list;
}
if (typeof restrictionList === "string") {
restrictionList = [restrictionList];
}
var result = [];
restrictionList.forEach(function (r) {
if (list.indexOf(r) !== -1) {
result.push(r);
}
});
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getAllDocsByExample
////////////////////////////////////////////////////////////////////////////////
function DOCUMENTS_BY_EXAMPLE (collectionList, example) {
var res = [];
if (!example) {
example = {};
}
if (typeof example === "string") {
example = {_id : example};
}
collectionList.forEach(function (c) {
res = res.concat(COLLECTION(c).byExample(example).toArray());
});
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief GET ALL EDGE and VERTEX COLLECTION ACCORDING TO DIRECTION
////////////////////////////////////////////////////////////////////////////////
function RESOLVE_GRAPH_TO_DOCUMENTS (graphname, options) {
// check graph exists and load edgeDefintions
var graph = DOCUMENT_HANDLE("_graphs/" + graphname);
if (!graph) {
THROW(INTERNAL.errors.ERROR_GRAPH_INVALID_GRAPH, "GRAPH_EDGES");
}
var fromCollections = [], toCollection = [],edgeCollections = [];
graph.edgeDefinitions.forEach(function (def) {
if (options.direction === "outbound") {
edgeCollections = edgeCollections.concat(
FILTER_RESTRICTION(def.collection, options.edgeCollectionRestriction)
);
fromCollections = fromCollections.concat(
FILTER_RESTRICTION(def.from, options.startVertexCollectionRestriction)
);
toCollection = toCollection.concat(
FILTER_RESTRICTION(def.to, options.endVertexCollectionRestriction)
);
}
else if (options.direction === "inbound") {
edgeCollections = edgeCollections.concat(
FILTER_RESTRICTION(def.collection, options.edgeCollectionRestriction)
);
fromCollections = fromCollections.concat(
FILTER_RESTRICTION(def.to, options.endVertexCollectionRestriction)
);
toCollection = toCollection.concat(
FILTER_RESTRICTION(def.from, options.startVertexCollectionRestriction)
);
}
else if (options.direction === "any") {
edgeCollections = edgeCollections.concat(
FILTER_RESTRICTION(def.collection, options.edgeCollectionRestriction)
);
fromCollections = fromCollections.concat(
FILTER_RESTRICTION(def.from.concat(def.to), options.startVertexCollectionRestriction)
);
toCollection = toCollection.concat(
FILTER_RESTRICTION(def.from.concat(def.to), options.endVertexCollectionRestriction)
);
}
else {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_EDGES");
}
});
var removeDuplicates = function(elem, pos, self) {
return self.indexOf(elem) === pos;
};
return {
fromVertices :DOCUMENTS_BY_EXAMPLE(
fromCollections.filter(removeDuplicates), options.fromVertexExample
),
toVertices : DOCUMENTS_BY_EXAMPLE(
toCollection.filter(removeDuplicates), options.toVertexExample
),
edges : DOCUMENTS_BY_EXAMPLE(edgeCollections.filter(removeDuplicates), options.edgeExample)
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected neighbors
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_NEIGHBORS (graphName,
vertex,
direction,
examples) {
vertexExample,
options) {
"use strict";
vertex = TO_ID(vertex);
var edges = GENERAL_GRAPH_EDGES(graphName, vertex, direction);
return FILTERED_EDGES(edges, vertex, direction, examples);
if (! options) {
options = { };
}
options.fromVertexExample = vertexExample;
if (!options.direction) {
options.direction = 'any';
}
var neighbors = [],
params = TRAVERSAL_PARAMS(), factory = TRAVERSAL.generalGraphDatasourceFactory(graphName);
params.minDepth = options.minDepth || 1;
params.maxDepth = options.maxDepth || 1;
params.followEdges = options.edgeExamples;
params.visitor = TRAVERSAL_NEIGHBOR_VISITOR;
var graph = RESOLVE_GRAPH_TO_DOCUMENTS(graphName, options);
graph.fromVertices.forEach(function (v) {
neighbors = neighbors.concat(TRAVERSAL_FUNC("GRAPH_NEIGHBORS",
factory,
v._id,
undefined,
options.direction,
params));
});
return neighbors;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected edges
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_EDGES (
graphName,
vertexExample,
options) {
"use strict";
var neighbors = GENERAL_GRAPH_NEIGHBORS(graphName,
vertexExample,
options), result = [];
neighbors.forEach(function (n) {
result.push(n.edge);
});
return result;
}
// -----------------------------------------------------------------------------
// --SECTION-- MODULE EXPORTS
// -----------------------------------------------------------------------------

View File

@ -62,8 +62,8 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
edge1 = db._createEdgeCollection("UnitTestsAhuacatlEdge1");
edge2 = db._createEdgeCollection("UnitTestsAhuacatlEdge2");
vertex1.save({ _key: "v1" });
vertex1.save({ _key: "v2" });
vertex1.save({ _key: "v1" , hugo : true});
vertex1.save({ _key: "v2" ,hugo : true});
vertex2.save({ _key: "v3" });
vertex2.save({ _key: "v4" });
vertex3.save({ _key: "v5" });
@ -88,7 +88,7 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
}
graph._create(
"bla3",
graph.edgeDefinitions(
graph._edgeDefinitions(
graph._undirectedRelationDefinition("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"),
graph._directedRelationDefinition("UnitTestsAhuacatlEdge2",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
@ -119,16 +119,17 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
testEdgesAny: function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any') SORT e.what RETURN e.what");
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'any'}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v1->v5", "v2->v1" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any' , [] , ['UnitTestsAhuacatlEdge1']) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v2->v1" ]);
/*actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'any' , edgeCollectionRestriction: ['UnitTestsAhuacatlEdge1']}) " +
"SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v2->v1" ]);*/
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any' , [{'what' : 'v2->v1'}]) SORT e.what RETURN e.what");
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'any' , edgeExamples : [{'what' : 'v2->v1'}]}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v2->v1" ]);
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any' , [{'what' : 'v2->v1'}]) SORT e.what RETURN e");
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'any' , edgeExamples : [{'what' : 'v2->v1'}]}) SORT e.what RETURN e");
assertEqual(actual[0].edge.what , "v2->v1");
assertEqual(actual[0].vertex._key , "v2");
},
@ -140,16 +141,16 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
testEdgesIn: function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', 'inbound') SORT e.what RETURN e.what");
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', {direction : 'inbound'}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v5", "v2->v5", "v3->v5"]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', 'inbound' , null , 'UnitTestsAhuacatlEdge2') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v5", "v2->v5", "v3->v5"]);
/*actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', {direction : 'inbound' ,edgeCollectionRestriction: 'UnitTestsAhuacatlEdge2'}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v5", "v2->v5", "v3->v5"]);*/
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', 'inbound' , [{'what' : 'v2->v5'}]) SORT e.what RETURN e.what");
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex3/v5', {direction : 'inbound' , edgeExamples : [{'what' : 'v2->v5'}]}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v2->v5" ]);
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex3/v5', 'inbound' , [{'what' : 'v2->v5'}]) SORT e.what RETURN e");
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex3/v5', {direction : 'inbound' , edgeExamples : [{'what' : 'v2->v5'}]}) SORT e.what RETURN e");
assertEqual(actual[0].edge.what , "v2->v5");
assertEqual(actual[0].vertex._key , "v2");
},
@ -162,20 +163,44 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
testEdgesOut: function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'outbound') SORT e.what RETURN e.what");
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'outbound'}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v1->v5"]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'outbound' , null , 'UnitTestsAhuacatlEdge2') SORT e.what RETURN e.what");
/*actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'outbound' ,edgeCollectionRestriction: 'UnitTestsAhuacatlEdge2'}) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v5"]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'outbound' , [{'what' : 'v2->v5'}]) SORT e.what RETURN e.what");
*/
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'outbound' ,edgeExamples : [{'what' : 'v2->v5'}]}) SORT e.what RETURN e.what");
assertEqual(actual, []);
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex1/v1', 'outbound') SORT e.what RETURN e");
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', 'UnitTestsAhuacatlVertex1/v1', {direction : 'outbound'}) SORT e.what RETURN e");
assertEqual(actual[0].edge.what , "v1->v2");
assertEqual(actual[0].vertex._key , "v2");
assertEqual(actual[1].edge.what , "v1->v5");
assertEqual(actual[1].vertex._key , "v5");
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', { hugo : true } , {direction : 'outbound'}) SORT e.edge.what RETURN e");
assertEqual(actual[0].edge.what , "v1->v2");
assertEqual(actual[0].vertex._key , "v2");
assertEqual(actual[1].edge.what , "v1->v5");
assertEqual(actual[1].vertex._key , "v5");
assertEqual(actual[2].edge.what , "v2->v1");
assertEqual(actual[2].vertex._key , "v1");
assertEqual(actual[3].edge.what , "v2->v5");
assertEqual(actual[3].vertex._key , "v5");
actual = getQueryResults("FOR e IN GRAPH_NEIGHBORS('bla3', { hugo : true } , {direction : 'outbound', endVertexCollectionRestriction : 'UnitTestsAhuacatlVertex3' }) " +
"SORT e.edge.what RETURN e");
assertEqual(actual[0].edge.what , "v1->v2");
assertEqual(actual[0].vertex._key , "v2");
assertEqual(actual[1].edge.what , "v1->v5");
assertEqual(actual[1].vertex._key , "v5");
assertEqual(actual[2].edge.what , "v2->v1");
assertEqual(actual[2].vertex._key , "v1");
assertEqual(actual[3].edge.what , "v2->v5");
assertEqual(actual[3].vertex._key , "v5");
},
////////////////////////////////////////////////////////////////////////////////
@ -183,11 +208,11 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
////////////////////////////////////////////////////////////////////////////////
testEdgesExceptions: function () {
assertQueryError(errors.ERROR_GRAPH_INVALID_GRAPH.code, "FOR e IN GRAPH_EDGES('notExistingGraph', 'UnitTestsAhuacatlVertex1/v1', 'outbound') RETURN e.what");
/*assertQueryError(errors.ERROR_GRAPH_INVALID_GRAPH.code, "FOR e IN GRAPH_EDGES('notExistingGraph', 'UnitTestsAhuacatlVertex1/v1', 'outbound') RETURN e.what");*/
assertQueryError(errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code, "FOR e IN GRAPH_EDGES('bla3', 'NotExistingVertex', 'outbound') RETURN e.what");
/*assertQueryError(errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code, "FOR e IN GRAPH_EDGES('bla3', 'NotExistingVertex', 'outbound') RETURN e.what");*/
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'noDirection') RETURN e.what");
/*assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'noDirection') RETURN e.what");*/
}
}
@ -241,7 +266,7 @@ function ahuacatlQueryGeneralPathsTestSuite() {
}
var g = graph._create(
"bla3",
graph.edgeDefinitions(
graph._edgeDefinitions(
graph._undirectedRelationDefinition("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"),
graph._directedRelationDefinition("UnitTestsAhuacatlEdge2",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
@ -411,7 +436,7 @@ function ahuacatlQueryGeneralTraversalTestSuite() {
}
var g = graph._create(
"werKenntWen",
graph.edgeDefinitions(
graph._edgeDefinitions(
graph._undirectedRelationDefinition(KenntAnderenBerliner, "UnitTests_Berliner"),
graph._directedRelationDefinition(KenntAnderen,
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"],
@ -453,11 +478,9 @@ function ahuacatlQueryGeneralTraversalTestSuite() {
var actual, result= [];
actual = getQueryResults("FOR e IN GRAPH_TRAVERSAL('werKenntWen', 'UnitTests_Hamburger/Caesar', 'outbound') RETURN e");
//require("internal").print(actual);
actual.forEach(function (s) {
result.push(s.vertex._key);
});
//require("internal").print(result)
assertEqual(result, [
"Caesar",
"Anton",

View File

@ -243,7 +243,7 @@ static TRI_shape_path_t const* FindShapePathByName (TRI_shaper_t* shaper,
if (ptr != prev) {
if (create) {
aids[count++] = shaper->findOrCreateAttributeByName(shaper, prev, isLocked);
aids[count++] = shaper->findOrCreateAttributeByName(shaper, prev);
}
else {
aids[count] = shaper->lookupAttributeByName(shaper, prev);
@ -395,15 +395,14 @@ int TRI_InitShaper (TRI_shaper_t* shaper, TRI_memory_zone_t* zone) {
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyShaper (TRI_shaper_t* shaper) {
size_t n = shaper->_attributePathsByName._nrAlloc;
size_t i;
size_t const n = shaper->_attributePathsByName._nrAlloc;
// only free pointers in attributePathsByName
// (attributePathsByPid contains the same pointers!)
for (i = 0; i < n; ++i) {
for (size_t i = 0; i < n; ++i) {
void* data = shaper->_attributePathsByName._table[i];
if (data) {
if (data != nullptr) {
TRI_Free(shaper->_memoryZone, data);
}
}

View File

@ -90,10 +90,10 @@ TRI_basic_shapes_t;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_shaper_s {
TRI_shape_aid_t (*findOrCreateAttributeByName) (struct TRI_shaper_s*, char const*, bool);
TRI_shape_aid_t (*findOrCreateAttributeByName) (struct TRI_shaper_s*, char const*);
TRI_shape_aid_t (*lookupAttributeByName) (struct TRI_shaper_s*, char const*);
char const* (*lookupAttributeId) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_t const* (*findShape) (struct TRI_shaper_s*, TRI_shape_t*, bool, bool);
TRI_shape_t const* (*findShape) (struct TRI_shaper_s*, TRI_shape_t*, bool);
TRI_shape_t const* (*lookupShapeId) (struct TRI_shaper_s*, TRI_shape_sid_t);
int64_t (*lookupAttributeWeight) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_path_t const* (*lookupAttributePathByPid) (struct TRI_shaper_s*, TRI_shape_pid_t);

View File

@ -581,7 +581,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
shape->_sidEntry = s;
shape->_sizeEntry = l;
found = shaper->findShape(shaper, &shape->base, create, isLocked);
found = shaper->findShape(shaper, &shape->base, create);
if (found == NULL) {
for (p = values; p < e; ++p) {
@ -648,7 +648,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
shape->_sidEntry = s;
found = shaper->findShape(shaper, &shape->base, create, isLocked);
found = shaper->findShape(shaper, &shape->base, create);
if (found == NULL) {
for (p = values; p < e; ++p) {
@ -830,7 +830,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
}
// first find an identifier for the name
p->_aid = shaper->findOrCreateAttributeByName(shaper, key->_value._string.data, isLocked);
p->_aid = shaper->findOrCreateAttributeByName(shaper, key->_value._string.data);
// convert value
if (p->_aid == 0) {
@ -986,7 +986,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
// lookup this shape
found = shaper->findShape(shaper, &a->base, create, isLocked);
found = shaper->findShape(shaper, &a->base, create);
if (found == NULL) {
TRI_Free(shaper->_memoryZone, a);

View File

@ -51,8 +51,7 @@ static int FillShapeValueJson (TRI_shaper_t* shaper,
v8::Handle<v8::Value> const json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked);
bool create);
static v8::Handle<v8::Value> JsonShapeData (TRI_shaper_t* shaper,
TRI_shape_t const* shape,
@ -262,8 +261,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper,
v8::Handle<v8::Array> const json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
bool create) {
size_t total;
TRI_shape_value_t* values;
@ -315,7 +313,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper,
for (uint32_t i = 0; i < n; ++i, ++p) {
v8::Handle<v8::Value> el = json->Get(i);
int res = FillShapeValueJson(shaper, p, el, seenHashes, seenObjects, create, isLocked);
int res = FillShapeValueJson(shaper, p, el, seenHashes, seenObjects, create);
if (res != TRI_ERROR_NO_ERROR) {
for (e = p, p = values; p < e; ++p) {
@ -373,7 +371,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper,
shape->_sidEntry = s;
shape->_sizeEntry = l;
found = shaper->findShape(shaper, &shape->base, create, isLocked);
found = shaper->findShape(shaper, &shape->base, create);
if (found == 0) {
for (p = values; p < e; ++p) {
@ -449,7 +447,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper,
shape->_sidEntry = s;
// if found returns non-NULL, it will free the shape!!
found = shaper->findShape(shaper, &shape->base, create, isLocked);
found = shaper->findShape(shaper, &shape->base, create);
if (found == 0) {
for (p = values; p < e; ++p) {
@ -579,8 +577,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper,
v8::Handle<v8::Object> const json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
bool create) {
size_t total;
size_t f;
@ -635,7 +632,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper,
}
if (create) {
p->_aid = shaper->findOrCreateAttributeByName(shaper, *keyStr, isLocked);
p->_aid = shaper->findOrCreateAttributeByName(shaper, *keyStr);
}
else {
p->_aid = shaper->lookupAttributeByName(shaper, *keyStr);
@ -653,7 +650,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper,
}
}
else {
res = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects, create, isLocked);
res = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects, create);
}
if (res != TRI_ERROR_NO_ERROR) {
@ -802,7 +799,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
// lookup this shape
found = shaper->findShape(shaper, &a->base, create, isLocked);
found = shaper->findShape(shaper, &a->base, create);
if (found == 0) {
LOG_TRACE("shaper failed to find shape %d", (int) a->base._type);
@ -829,8 +826,7 @@ static int FillShapeValueJson (TRI_shaper_t* shaper,
v8::Handle<v8::Value> const json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
bool create) {
// check for cycles
if (json->IsObject()) {
v8::Handle<v8::Object> o = json->ToObject();
@ -882,11 +878,11 @@ static int FillShapeValueJson (TRI_shaper_t* shaper,
}
else if (json->IsArray()) {
return FillShapeValueList(shaper, dst, v8::Handle<v8::Array>::Cast(json), seenHashes, seenObjects, create, isLocked);
return FillShapeValueList(shaper, dst, v8::Handle<v8::Array>::Cast(json), seenHashes, seenObjects, create);
}
else if (json->IsObject()) {
int res = FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects, create, isLocked);
int res = FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects, create);
seenObjects.pop_back();
return res;
}
@ -1453,13 +1449,12 @@ v8::Handle<v8::Value> TRI_JsonShapeData (TRI_shaper_t* shaper,
TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const object,
TRI_shaper_t* shaper,
bool create,
bool isLocked) {
bool create) {
TRI_shape_value_t dst;
set<int> seenHashes;
vector< v8::Handle<v8::Object> > seenObjects;
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create, isLocked);
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create);
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_RESULT_ELEMENT_NOT_FOUND) {
@ -1491,13 +1486,12 @@ TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const object,
int TRI_FillShapedJsonV8Object (v8::Handle<v8::Value> const object,
TRI_shaped_json_t* result,
TRI_shaper_t* shaper,
bool create,
bool isLocked) {
bool create) {
TRI_shape_value_t dst;
set<int> seenHashes;
vector< v8::Handle<v8::Object> > seenObjects;
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create, isLocked);
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create);
if (res != TRI_ERROR_NO_ERROR) {
if (res != TRI_RESULT_ELEMENT_NOT_FOUND) {

View File

@ -70,7 +70,6 @@ v8::Handle<v8::Value> TRI_JsonShapeData (TRI_shaper_t*,
TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const,
TRI_shaper_t*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
@ -80,7 +79,6 @@ TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const,
int TRI_FillShapedJsonV8Object (v8::Handle<v8::Value> const,
TRI_shaped_json_t*,
TRI_shaper_t*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////