Files
Immich/server/src/queries/access.repository.sql
T
bo0tzzandCodex c7a5ac3d11 perf(server): check shared link asset access without scanning the album (#32411)
* perf(server): check shared link asset access without scanning the album

checkSharedLinkAccess runs on every thumbnail, preview, playback and asset
info request made through a shared link. It joined every asset of the
link's album and only then filtered on an array overlap across four
outer-joined columns, so each request cost O(album size).

Split it into two branches (link assets, album assets) that find the
requested ids through the asset pkey / livePhotoVideoId index and then
probe the album_asset pkey.

Median per request, PG 14, 1.36M-asset instance:

| album behind the link | before | after   |
|-----------------------|--------|---------|
| 290 assets            | 2.1 ms | 0.17 ms |
| 150k assets           | 296 ms | 0.19 ms |

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
(cherry picked from commit bb024c862609c9e2baffc08fef795cfa3418df16)
2026-10-14 21:24:13 +03:00

367 lines
7.8 KiB
SQL

-- NOTE: This file is auto generated by ./sql-generator
-- AccessRepository.activity.checkOwnerAccess
select
"activity"."id"
from
"activity"
where
"activity"."id" in ($1)
and "activity"."userId" = $2
-- AccessRepository.activity.checkAlbumOwnerAccess
select
"activity"."id"
from
"activity"
inner join "album" on "activity"."albumId" = "album"."id"
and "album"."deletedAt" is null
inner join "album_user" on "album"."id" = "album_user"."albumId"
and "album_user"."role" = 'owner'
and "album_user"."userId" = $1::uuid
where
"activity"."id" in ($2)
-- AccessRepository.activity.checkCreateAccess
select
"album"."id"
from
"album"
inner join "album_user" as "albumUsers" on "albumUsers"."albumId" = "album"."id"
inner join "user" on "user"."id" = "albumUsers"."userId"
and "user"."deletedAt" is null
where
"album"."id" in ($1)
and "album"."isActivityEnabled" = $2
and "user"."id" = $3
and "album"."deletedAt" is null
-- AccessRepository.album.checkOwnerAccess
select
"album"."id"
from
"album"
inner join "album_user" on "album"."id" = "album_user"."albumId"
and "album_user"."role" = 'owner'
and "album_user"."userId" = $1
where
"album"."id" in ($2)
and "album"."deletedAt" is null
-- AccessRepository.album.checkSharedAlbumAccess
select
"album"."id"
from
"album"
inner join "album_user" on "album_user"."albumId" = "album"."id"
inner join "user" on "user"."id" = "album_user"."userId"
and "user"."deletedAt" is null
where
"album"."id" in ($1)
and "album"."deletedAt" is null
and "user"."id" = $2
and "album_user"."role" in ($3, $4)
-- AccessRepository.album.checkSharedLinkAccess
select
"shared_link"."albumId"
from
"shared_link"
where
"shared_link"."id" = $1
and "shared_link"."albumId" in ($2)
-- AccessRepository.asset.checkAlbumAccess
with
"target" as (
select
array[$1]::uuid[] as "ids"
)
select
"asset"."id",
"asset"."livePhotoVideoId"
from
"album"
inner join "album_asset" as "albumAssets" on "album"."id" = "albumAssets"."albumId"
inner join "asset" on "asset"."id" = "albumAssets"."assetId"
and "asset"."deletedAt" is null
left join "album_user" as "albumUsers" on "albumUsers"."albumId" = "album"."id"
left join "user" on "user"."id" = "albumUsers"."userId"
and "user"."deletedAt" is null
cross join "target"
where
(
"asset"."id" = any (target.ids)
or "asset"."livePhotoVideoId" = any (target.ids)
)
and "user"."id" = $2
and "album"."deletedAt" is null
-- AccessRepository.asset.checkOwnerAccess
select
"asset"."id"
from
"asset"
where
"asset"."id" in ($1)
and "asset"."ownerId" = $2
and "asset"."visibility" != $3
-- AccessRepository.asset.checkPartnerAccess
select
"asset"."id"
from
"partner"
inner join "user" as "sharedBy" on "sharedBy"."id" = "partner"."sharedById"
and "sharedBy"."deletedAt" is null
inner join "asset" on "asset"."ownerId" = "sharedBy"."id"
and "asset"."deletedAt" is null
where
"partner"."sharedWithId" = $1
and (
"asset"."visibility" = 'timeline'
or "asset"."visibility" = 'hidden'
)
and "asset"."id" in ($2)
-- AccessRepository.asset.checkSharedLinkAccess
with
"target" as (
select
array[$1]::uuid[] as "ids"
),
"link" as (
select
"shared_link"."id",
"shared_link"."albumId"
from
"shared_link"
where
"shared_link"."id" = $2
)
select
"asset"."id",
"asset"."livePhotoVideoId"
from
"asset"
cross join "target"
inner join lateral (
select
1 as "match"
from
"link"
inner join "shared_link_asset" on "shared_link_asset"."sharedLinkId" = "link"."id"
where
"shared_link_asset"."assetId" = "asset"."id"
union all
select
1 as "match"
from
"link"
inner join "album" on "album"."id" = "link"."albumId"
and "album"."deletedAt" is null
inner join "album_asset" on "album_asset"."albumId" = "album"."id"
where
"album_asset"."assetId" = "asset"."id"
limit
$3
) as "membership" on true
where
"asset"."deletedAt" is null
and (
"asset"."id" = any ("target"."ids")
or "asset"."livePhotoVideoId" = any ("target"."ids")
)
-- AccessRepository.assetFile.checkOwnerAccess
select
"asset_file"."id"
from
"asset_file"
inner join "asset" on "asset"."id" = "asset_file"."assetId"
where
"asset"."visibility" != $1
and "asset"."ownerId" = $2
and "asset_file"."id" in ($3)
-- AccessRepository.authDevice.checkOwnerAccess
select
"session"."id"
from
"session"
where
"session"."userId" = $1
and "session"."id" in ($2)
-- AccessRepository.duplicate.checkOwnerAccess
select
"asset"."duplicateId"
from
"asset"
where
"asset"."duplicateId" in ($1)
and "asset"."ownerId" = $2
and "asset"."deletedAt" is null
-- AccessRepository.memory.checkOwnerAccess
select
"memory"."id"
from
"memory"
where
"memory"."id" in ($1)
and "memory"."ownerId" = $2
and "memory"."deletedAt" is null
-- AccessRepository.notification.checkOwnerAccess
select
"notification"."id"
from
"notification"
where
"notification"."id" in ($1)
and "notification"."userId" = $2
-- AccessRepository.clusterGroup.checkInviteAccess
select
"cluster_group_request"."clusterGroupId"
from
"cluster_group_request"
where
"cluster_group_request"."clusterGroupId" in ($1)
and "cluster_group_request"."userId" = $2
-- AccessRepository.clusterGroup.checkOwnerAccess
select
"user"."clusterGroupId"
from
"user"
where
"user"."clusterGroupId" in ($1)
and "user"."id" = $2
-- AccessRepository.clusterGroupRequest.checkOwnerAccess
select
"cluster_group_request"."id"
from
"cluster_group_request"
where
"cluster_group_request"."id" in ($1)
and "cluster_group_request"."userId" = $2
-- AccessRepository.clusterGroupRequest.checkGroupAccess
select
"cluster_group_request"."id"
from
"cluster_group_request"
where
"cluster_group_request"."id" in ($1)
and "cluster_group_request"."clusterGroupId" = (
select
"user"."clusterGroupId"
from
"user"
where
"user"."id" = $2
)
-- AccessRepository.person.checkAccess
select
"personGroupId",
"ownerId"
from
(
select
unnest($1::uuid[]) as "personGroupId",
unnest($2::uuid[]) as "ownerId"
) as "people"
where
(
exists (
select
*
from
"person"
where
"people"."personGroupId" = "person"."personGroupId"
and "people"."ownerId" = "person"."ownerId"
and "person"."ownerId" = $3
)
or exists (
select
*
from
"person_user"
where
"person_user"."sharedWithId" = $4
and "person_user"."role" in ($5)
and "people"."personGroupId" = "person_user"."personGroupId"
and "people"."ownerId" = "person_user"."sharedById"
)
)
-- AccessRepository.person.checkFaceOwnerAccess
select
"asset_face"."id"
from
"asset_face"
left join "asset" on "asset"."id" = "asset_face"."assetId"
and "asset"."deletedAt" is null
where
"asset_face"."id" in ($1)
and "asset"."ownerId" = $2
-- AccessRepository.partner.checkUpdateAccess
select
"partner"."sharedById"
from
"partner"
where
"partner"."sharedById" in ($1)
and "partner"."sharedWithId" = $2
-- AccessRepository.session.checkOwnerAccess
select
"session"."id"
from
"session"
where
"session"."id" in ($1)
and "session"."userId" = $2
-- AccessRepository.stack.checkOwnerAccess
select
"stack"."id"
from
"stack"
where
"stack"."id" in ($1)
and "stack"."ownerId" = $2
-- AccessRepository.tag.checkOwnerAccess
select
"tag"."id"
from
"tag"
where
"tag"."id" in ($1)
and "tag"."userId" = $2
-- AccessRepository.timeline.checkPartnerAccess
select
"partner"."sharedById"
from
"partner"
where
"partner"."sharedById" in ($1)
and "partner"."sharedWithId" = $2
-- AccessRepository.workflow.checkOwnerAccess
select
"workflow"."id"
from
"workflow"
where
"workflow"."id" in ($1)
and "workflow"."ownerId" = $2