1
0
Fork 0

fix cross-collection queries in AQL

This commit is contained in:
Jan Steemann 2013-02-05 10:56:28 +01:00
parent 2263e959fe
commit e06329db48
6 changed files with 87 additions and 11 deletions

View File

@ -306,7 +306,19 @@ namespace triagens {
TRI_vocbase_col_t* collection = TRI_CheckCollectionTransaction(this->_trx, cid, type); TRI_vocbase_col_t* collection = TRI_CheckCollectionTransaction(this->_trx, cid, type);
if (collection == 0) { if (collection == 0) {
return _setupError = TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION; // adding an unknown collection...
int res = TRI_ERROR_NO_ERROR;
if (type == TRI_TRANSACTION_READ && this->isReadOnlyTransaction()) {
res = TRI_AddDelayedReadCollectionTransaction(this->_trx, cid);
}
else {
res = TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION;
}
if (res != TRI_ERROR_NO_ERROR) {
return _setupError = res;
}
} }
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;

View File

@ -427,7 +427,7 @@ void TRI_FreeTransactionContext (TRI_transaction_context_t* const context) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief free all data associated with a specific collection /// @brief free all data associated with a specific collection
/// TODO: this function must be called for all collections that are dropped /// this function gets called for all collections that are dropped
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const context, void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const context,
@ -1158,7 +1158,6 @@ TRI_vocbase_col_t* TRI_CheckCollectionTransaction (TRI_transaction_t* const trx,
// the vector is sorted by collection names // the vector is sorted by collection names
n = trx->_collections._length; n = trx->_collections._length;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
collection = TRI_AtVectorPointer(&trx->_collections, i); collection = TRI_AtVectorPointer(&trx->_collections, i);
if (cid < collection->_cid) { if (cid < collection->_cid) {
@ -1240,6 +1239,48 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to an already running transaction
/// opens it and locks it in read-only mode
////////////////////////////////////////////////////////////////////////////////
int TRI_AddDelayedReadCollectionTransaction (TRI_transaction_t* const trx,
const TRI_transaction_cid_t cid) {
TRI_transaction_collection_t* collection;
size_t i, n;
int res;
n = trx->_collections._length;
for (i = 0; i < n; ++i) {
collection = TRI_AtVectorPointer(&trx->_collections, i);
if (cid < collection->_cid) {
// collection is not contained in vector
collection = CreateCollection(cid, TRI_TRANSACTION_READ);
if (collection == NULL) {
// out of memory
return TRI_ERROR_OUT_OF_MEMORY;
}
TRI_InsertVectorPointer(&trx->_collections, collection, i);
collection->_collection = TRI_UseCollectionByIdVocBase(trx->_context->_vocbase, collection->_cid);
if (collection->_collection == NULL) {
return TRI_errno();
}
res = LockCollection(collection, TRI_TRANSACTION_READ);
return res;
}
}
// we should not get here. Otherwise this is a logic error
LOG_WARNING("logic error. should have inserted collection");
return TRI_ERROR_INTERNAL;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief start a transaction /// @brief start a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -401,6 +401,13 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const,
const TRI_transaction_cid_t, const TRI_transaction_cid_t,
const TRI_transaction_type_e); const TRI_transaction_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to an already running transaction, read-only mode
////////////////////////////////////////////////////////////////////////////////
int TRI_AddDelayedReadCollectionTransaction (TRI_transaction_t* const,
const TRI_transaction_cid_t);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief request a lock for a collection /// @brief request a lock for a collection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -279,12 +279,14 @@ static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
TRI_document_collection_t* document; TRI_document_collection_t* document;
TRI_vocbase_col_t* collection; TRI_vocbase_col_t* collection;
TRI_vocbase_t* vocbase; TRI_vocbase_t* vocbase;
TRI_voc_cid_t cid;
regmatch_t matches[3]; regmatch_t matches[3];
regex_t re; regex_t re;
int res; int res;
size_t i; size_t i;
collection = data; collection = data;
cid = 0;
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection); TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
@ -308,6 +310,8 @@ static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
return false; return false;
} }
cid = collection->_cid;
document = (TRI_document_collection_t*) collection->_collection; document = (TRI_document_collection_t*) collection->_collection;
res = TRI_CloseDocumentCollection(document); res = TRI_CloseDocumentCollection(document);
@ -432,6 +436,10 @@ static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
regfree(&re); regfree(&re);
} }
if (cid > 0) {
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, cid);
}
return true; return true;
} }

View File

@ -2697,7 +2697,7 @@ function TRAVERSAL_FUNC (func, vertexCollection, edgeCollection, startVertex, di
var v = null; var v = null;
var result = [ ]; var result = [ ];
try { try {
v = vertexCollection.document(startVertex); v = INTERNAL.db._document(startVertex);
} }
catch (err) { catch (err) {
} }

View File

@ -183,14 +183,18 @@ function ahuacatlCrossCollection () {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
testTraversal1 : function () { testTraversal1 : function () {
var d1 = vertex1.save({ _key: "test1" }); var d1 = vertex1.save({ _key: "test1", a: 1 });
var d2 = vertex1.save({ _key: "test2" }); var d2 = vertex1.save({ _key: "test2", a: 2 });
var d3 = vertex2.save({ _key: "test3" }); var d3 = vertex2.save({ _key: "test3", a: 3 });
var e1 = edge.save(d1._id, d2._id, { }); var e1 = edge.save(d1._id, d2._id, { });
var e2 = edge.save(d2._id, d3._id, { }); var e2 = edge.save(d2._id, d3._id, { });
var actual = getQueryResults("FOR t IN TRAVERSAL(" + vn1 + ", " + en + ", " + JSON.stringify(d1._id) + ", 'outbound', { }) RETURN t"); var actual = getQueryResults("FOR t IN TRAVERSAL(" + vn1 + ", " + en + ", " + JSON.stringify(d1._id) + ", 'outbound', { }) RETURN t");
assertEqual(2, actual.length); assertEqual(3, actual.length);
assertEqual(1, actual[0].vertex.a);
assertEqual(2, actual[1].vertex.a);
assertEqual(3, actual[2].vertex.a);
}, },
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -198,12 +202,16 @@ function ahuacatlCrossCollection () {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
testTraversal2 : function () { testTraversal2 : function () {
var d1 = vertex1.save({ _key: "test1" }); var d1 = vertex1.save({ _key: "test1", a: 1 });
var d2 = vertex2.save({ _key: "test2" }); var d2 = vertex2.save({ _key: "test2", a: 2 });
var d3 = vertex2.save({ _key: "test3", a: 3 });
var e1 = edge.save(d1._id, d2._id, { }); var e1 = edge.save(d1._id, d2._id, { });
var e2 = edge.save(d2._id, d3._id, { });
var actual = getQueryResults("FOR t IN TRAVERSAL(" + vn1 + ", " + en + ", " + JSON.stringify(d2._id) + ", 'outbound', { }) RETURN t"); var actual = getQueryResults("FOR t IN TRAVERSAL(" + vn1 + ", " + en + ", " + JSON.stringify(d2._id) + ", 'outbound', { }) RETURN t");
assertEqual(0, actual.length); assertEqual(2, actual.length);
assertEqual(2, actual[0].vertex.a);
assertEqual(3, actual[1].vertex.a);
} }
}; };