summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2016-10-06 14:27:44 +0200
committerRoeland Jago Douma <roeland@famdouma.nl>2016-10-06 19:31:28 +0200
commit990f4a182de96b96b2d13ad4d29adaba1601c5b1 (patch)
tree252913da0a1785588f4ce176b908da94d1e52d3a /lib
parenta0b34dfd2f5e6ed1ea5e35692816acf73f3ede4e (diff)
downloadnextcloud-server-990f4a182de96b96b2d13ad4d29adaba1601c5b1.tar.gz
nextcloud-server-990f4a182de96b96b2d13ad4d29adaba1601c5b1.zip
More efficient group share resolving
When resolving a group share to the user group share we used to do this on a per share basis. Now we try to do this for all group shares at once. Of course still chunked. Before: N incomming group shares this would mean 1 + N queries Now: N incomming roups shares this would mean 1 + 1 queries Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Share20/DefaultShareProvider.php79
1 files changed, 49 insertions, 30 deletions
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index f33c297b02d..82ab36caf0f 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -543,7 +543,7 @@ class DefaultShareProvider implements IShareProvider {
// If the recipient is set for a group share resolve to that user
if ($recipientId !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- $share = $this->resolveGroupShare($share, $recipientId);
+ $share = $this->resolveGroupShares([$share], $recipientId)[0];
}
return $share;
@@ -679,11 +679,8 @@ class DefaultShareProvider implements IShareProvider {
/*
* Resolve all group shares to user specific shares
- * TODO: Optmize this!
*/
- foreach($shares2 as $share) {
- $shares[] = $this->resolveGroupShare($share, $userId);
- }
+ $shares = $this->resolveGroupShares($shares2, $userId);
} else {
throw new BackendError('Invalid backend');
}
@@ -772,37 +769,59 @@ class DefaultShareProvider implements IShareProvider {
}
/**
- * Resolve a group share to a user specific share
- * Thus if the user moved their group share make sure this is properly reflected here.
- *
- * @param \OCP\Share\IShare $share
- * @param string $userId
- * @return Share Returns the updated share if one was found else return the original share.
+ * @param Share[] $shares
+ * @param $userId
+ * @return Share[] The updates shares if no update is found for a share return the original
*/
- private function resolveGroupShare(\OCP\Share\IShare $share, $userId) {
- $qb = $this->dbConn->getQueryBuilder();
+ private function resolveGroupShares($shares, $userId) {
+ $result = [];
- $stmt = $qb->select('*')
- ->from('share')
- ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
- ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
- ->andWhere($qb->expr()->orX(
- $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
- $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
- ))
- ->setMaxResults(1)
- ->execute();
+ $start = 0;
+ while(true) {
+ /** @var Share[] $shareSlice */
+ $shareSlice = array_slice($shares, $start, 100);
+ $start += 100;
+
+ if ($shareSlice === []) {
+ break;
+ }
+
+ /** @var int[] $ids */
+ $ids = [];
+ /** @var Share[] $shareMap */
+ $shareMap = [];
+
+ foreach ($shareSlice as $share) {
+ $ids[] = (int)$share->getId();
+ $shareMap[$share->getId()] = $share;
+ }
- $data = $stmt->fetch();
- $stmt->closeCursor();
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $query = $qb->select('*')
+ ->from('share')
+ ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
+ ->andWhere($qb->expr()->orX(
+ $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
+ $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
+ ));
- if ($data !== false) {
- $share->setPermissions((int)$data['permissions']);
- $share->setTarget($data['file_target']);
+ $stmt = $query->execute();
+
+ while($data = $stmt->fetch()) {
+ $shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
+ $shareMap[$data['parent']]->setTarget($data['file_target']);
+ }
+
+ $stmt->closeCursor();
+
+ foreach ($shareMap as $share) {
+ $result[] = $share;
+ }
}
- return $share;
+ return $result;
}
/**