Commit 1adcbb3e authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

MOVE: commit current transaction before emitting notification

parent 99bd2520
......@@ -44,97 +44,95 @@ void Move::itemsRetrieved(const QList<qint64> &ids)
const QDateTime mtime = QDateTime::currentDateTime();
if (qb.exec()) {
const QVector<PimItem> items = qb.result();
if (items.isEmpty()) {
successResponse<Protocol::MoveItemsResponse>();
return;
}
if (!qb.exec()) {
failureResponse("Unable to execute query");
return;
}
// Split the list by source collection
QMap<Entity::Id /* collection */, PimItem> toMove;
QMap<Entity::Id /* collection */, Collection> sources;
Q_FOREACH (/*sic!*/ PimItem item, items) {
if (!item.isValid()) {
failureResponse("Invalid item in result set!?");
return;
}
const QVector<PimItem> items = qb.result();
if (items.isEmpty()) {
successResponse<Protocol::MoveItemsResponse>();
return;
}
const Collection source = item.collection();
if (!source.isValid()) {
failureResponse("Item without collection found!?");
return;
}
if (!sources.contains(source.id())) {
sources.insert(source.id(), source);
}
// Split the list by source collection
QMap<Entity::Id /* collection */, PimItem> toMove;
QMap<Entity::Id /* collection */, Collection> sources;
Q_FOREACH (/*sic!*/ PimItem item, items) {
if (!item.isValid()) {
failureResponse("Invalid item in result set!?");
return;
}
Q_ASSERT(item.collectionId() != mDestination.id());
const Collection source = item.collection();
if (!source.isValid()) {
failureResponse("Item without collection found!?");
return;
}
if (!sources.contains(source.id())) {
sources.insert(source.id(), source);
}
item.setCollectionId(mDestination.id());
item.setAtime(mtime);
item.setDatetime(mtime);
// if the resource moved itself, we assume it did so because the change happend in the backend
if (connection()->context()->resource().id() != mDestination.resourceId()) {
item.setDirty(true);
}
Q_ASSERT(item.collectionId() != mDestination.id());
if (!item.update()) {
failureResponse("Unable to update item");
return;
}
item.setCollectionId(mDestination.id());
item.setAtime(mtime);
item.setDatetime(mtime);
// if the resource moved itself, we assume it did so because the change happend in the backend
if (connection()->context()->resource().id() != mDestination.resourceId()) {
item.setDirty(true);
}
toMove.insertMulti(source.id(), item);
if (!item.update()) {
failureResponse("Unable to update item");
return;
}
// Emit notification for each source collection separately
QVector<PimItem::Id> itemsToResetRID;
Collection source;
PimItem::List itemsToMove;
for (auto it = toMove.cbegin(), end = toMove.cend(); it != end; ++it) {
if (source.id() != it.key()) {
if (!itemsToMove.isEmpty()) {
store->notificationCollector()->itemsMoved(itemsToMove, source, mDestination);
}
source = sources.value(it.key());
itemsToMove.clear();
}
toMove.insertMulti(source.id(), item);
}
itemsToMove.push_back(*it);
if (!transaction.commit()) {
failureResponse("Unable to commit transaction.");
return;
}
// reset RID on inter-resource moves, but only after generating the change notification
// so that this still contains the old one for the source resource
const bool isInterResourceMove = it->collection().resource().id() != source.resource().id();
if (isInterResourceMove) {
itemsToResetRID.push_back(it->id());
// Emit notification for each source collection separately
QVector<PimItem::Id> itemsToResetRID;
Collection source;
PimItem::List itemsToMove;
for (auto it = toMove.cbegin(), end = toMove.cend(); it != end; ++it) {
if (source.id() != it.key()) {
if (!itemsToMove.isEmpty()) {
store->notificationCollector()->itemsMoved(itemsToMove, source, mDestination);
}
source = sources.value(it.key());
itemsToMove.clear();
}
if (!itemsToMove.isEmpty()) {
store->notificationCollector()->itemsMoved(itemsToMove, source, mDestination);
}
itemsToMove.push_back(*it);
// Batch-reset RID for all inter-resource moves
if (!itemsToResetRID.isEmpty()) {
QueryBuilder qb(PimItem::tableName(), QueryBuilder::Update);
qb.setColumnValue(PimItem::remoteIdColumn(), QString());
ItemQueryHelper::itemSetToQuery(itemsToResetRID, connection()->context(), qb);
if (!qb.exec()) {
failureResponse("Unable to update RID");
return;
}
// reset RID on inter-resource moves, but only after generating the change notification
// so that this still contains the old one for the source resource
const bool isInterResourceMove = it->collection().resource().id() != source.resource().id();
if (isInterResourceMove) {
itemsToResetRID.push_back(it->id());
}
} else {
failureResponse("Unable to execute query");
return;
}
if (!transaction.commit()) {
failureResponse("Unable to commit transaction.");
return;
if (!itemsToMove.isEmpty()) {
store->notificationCollector()->itemsMoved(itemsToMove, source, mDestination);
}
// Batch-reset RID for all inter-resource moves
if (!itemsToResetRID.isEmpty()) {
QueryBuilder qb(PimItem::tableName(), QueryBuilder::Update);
qb.setColumnValue(PimItem::remoteIdColumn(), QString());
ItemQueryHelper::itemSetToQuery(itemsToResetRID, connection()->context(), qb);
if (!qb.exec()) {
failureResponse("Unable to update RID");
return;
}
}
}
bool Move::parseStream()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment