Files
immich/server/src/queries/asset.repository.sql
Sergey Katsubo 2c54b506b3 fix(server): include the previous year in memories for January 1, 2, 3 (#23832)
* Test memory creation in advance

Use year 2035 to make sure it's in the future of current time of a test run

* Use target year instead of current year when fetching assets during memory creation

This fixes an edge case of creating memories in advance when target year is
different from current year.
Example: job runs on 2025-12-31 (current year is 2025) and creates memories
to be shown on 2026-01-01 (target year is 2026). If using _current_ year in
calculation then range of years is capped at (2025 - 1 = 2024) thus excluding
2025-01-01 from created memories. With _target_ year it is (2026 - 1 = 2025),
so 2025-01-01 will be included in memories.

* Update sql queries
2025-11-12 15:38:03 -06:00

507 lines
11 KiB
SQL

-- NOTE: This file is auto generated by ./sql-generator
-- AssetRepository.updateAllExif
update "asset_exif"
set
"model" = $1
where
"assetId" in ($2)
-- AssetRepository.updateDateTimeOriginal
update "asset_exif"
set
"dateTimeOriginal" = "dateTimeOriginal" + $1::interval,
"timeZone" = $2
where
"assetId" in ($3)
returning
"assetId",
"dateTimeOriginal",
"timeZone"
-- AssetRepository.getMetadata
select
"key",
"value",
"updatedAt"
from
"asset_metadata"
where
"assetId" = $1
-- AssetRepository.getMetadataByKey
select
"key",
"value",
"updatedAt"
from
"asset_metadata"
where
"assetId" = $1
and "key" = $2
-- AssetRepository.deleteMetadataByKey
delete from "asset_metadata"
where
"assetId" = $1
and "key" = $2
-- AssetRepository.getByDayOfYear
with
"res" as (
with
"today" as (
select
make_date(year::int, $1::int, $2::int) as "date"
from
generate_series(
(
select
date_part(
'year',
min(("localDateTime" at time zone 'UTC')::date)
)::int
from
asset
),
$3
) as "year"
)
select
"a".*,
to_json("asset_exif") as "exifInfo"
from
"today"
inner join lateral (
select
"asset".*
from
"asset"
inner join "asset_job_status" on "asset"."id" = "asset_job_status"."assetId"
where
"asset_job_status"."previewAt" is not null
and (asset."localDateTime" at time zone 'UTC')::date = today.date
and "asset"."ownerId" = any ($4::uuid[])
and "asset"."visibility" = $5
and exists (
select
from
"asset_file"
where
"assetId" = "asset"."id"
and "asset_file"."type" = $6
)
and "asset"."deletedAt" is null
order by
(asset."localDateTime" at time zone 'UTC')::date desc
limit
$7
) as "a" on true
inner join "asset_exif" on "a"."id" = "asset_exif"."assetId"
)
select
date_part(
'year',
("localDateTime" at time zone 'UTC')::date
)::int as "year",
json_agg("res") as "assets"
from
"res"
group by
("localDateTime" at time zone 'UTC')::date
order by
("localDateTime" at time zone 'UTC')::date desc
-- AssetRepository.getByIds
select
"asset".*
from
"asset"
where
"asset"."id" = any ($1::uuid[])
-- AssetRepository.getByIdsWithAllRelationsButStacks
select
"asset".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_face".*,
"person" as "person"
from
"asset_face"
left join lateral (
select
"person".*
from
"person"
where
"asset_face"."personId" = "person"."id"
) as "person" on true
where
"asset_face"."assetId" = "asset"."id"
and "asset_face"."deletedAt" is null
) as agg
) as "faces",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tag"
inner join "tag_asset" on "tag"."id" = "tag_asset"."tagId"
where
"asset"."id" = "tag_asset"."assetId"
) as agg
) as "tags",
to_json("asset_exif") as "exifInfo"
from
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"asset"."id" = any ($1::uuid[])
-- AssetRepository.deleteAll
delete from "asset"
where
"ownerId" = $1
-- AssetRepository.getByLibraryIdAndOriginalPath
select
"asset".*
from
"asset"
where
"libraryId" = $1::uuid
and "originalPath" = $2
limit
$3
-- AssetRepository.getAllByDeviceId
select
"deviceAssetId"
from
"asset"
where
"ownerId" = $1::uuid
and "deviceId" = $2
and "visibility" != $3
and "deletedAt" is null
-- AssetRepository.getLivePhotoCount
select
count(*) as "count"
from
"asset"
where
"livePhotoVideoId" = $1::uuid
-- AssetRepository.getFileSamples
select
"assetId",
"path"
from
"asset_file"
limit
3
-- AssetRepository.getById
select
"asset".*
from
"asset"
where
"asset"."id" = $1::uuid
limit
$2
-- AssetRepository.updateAll
update "asset"
set
"deviceId" = $1
where
"id" = any ($2::uuid[])
-- AssetRepository.getByChecksum
select
"asset".*
from
"asset"
where
"ownerId" = $1::uuid
and "checksum" = $2
and "libraryId" = $3::uuid
limit
$4
-- AssetRepository.getByChecksums
select
"id",
"checksum",
"deletedAt"
from
"asset"
where
"ownerId" = $1::uuid
and "checksum" in ($2)
-- AssetRepository.getUploadAssetIdByChecksum
select
"id"
from
"asset"
where
"ownerId" = $1::uuid
and "checksum" = $2
and "libraryId" is null
limit
$3
-- AssetRepository.getTimeBuckets
with
"asset" as (
select
date_trunc('MONTH', "localDateTime" AT TIME ZONE 'UTC') AT TIME ZONE 'UTC' as "timeBucket"
from
"asset"
where
"asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
)
select
("timeBucket" AT TIME ZONE 'UTC')::date::text as "timeBucket",
count(*) as "count"
from
"asset"
group by
"timeBucket"
order by
"timeBucket" desc
-- AssetRepository.getTimeBucket
with
"cte" as (
select
"asset"."duration",
"asset"."id",
"asset"."visibility",
asset."isFavorite"
and asset."ownerId" = $1 as "isFavorite",
asset.type = 'IMAGE' as "isImage",
asset."deletedAt" is not null as "isTrashed",
"asset"."livePhotoVideoId",
extract(
epoch
from
(
asset."localDateTime" AT TIME ZONE 'UTC' - asset."fileCreatedAt" at time zone 'UTC'
)
)::real / 3600 as "localOffsetHours",
"asset"."ownerId",
"asset"."status",
asset."fileCreatedAt" at time zone 'utc' as "fileCreatedAt",
encode("asset"."thumbhash", 'base64') as "thumbhash",
"asset_exif"."city",
"asset_exif"."country",
"asset_exif"."projectionType",
coalesce(
case
when asset_exif."exifImageHeight" = 0
or asset_exif."exifImageWidth" = 0 then 1
when "asset_exif"."orientation" in ('5', '6', '7', '8', '-90', '90') then round(
asset_exif."exifImageHeight"::numeric / asset_exif."exifImageWidth"::numeric,
3
)
else round(
asset_exif."exifImageWidth"::numeric / asset_exif."exifImageHeight"::numeric,
3
)
end,
1
) as "ratio",
"stack"
from
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join lateral (
select
array[stacked."stackId"::text, count('stacked')::text] as "stack"
from
"asset" as "stacked"
where
"stacked"."stackId" = "asset"."stackId"
and "stacked"."deletedAt" is null
and "stacked"."visibility" = $2
group by
"stacked"."stackId"
) as "stacked_assets" on true
where
"asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
and date_trunc('MONTH', "localDateTime" AT TIME ZONE 'UTC') AT TIME ZONE 'UTC' = $3
and not exists (
select
from
"stack"
where
"stack"."id" = "asset"."stackId"
and "stack"."primaryAssetId" != "asset"."id"
)
order by
"asset"."fileCreatedAt" desc
),
"agg" as (
select
coalesce(array_agg("city"), '{}') as "city",
coalesce(array_agg("country"), '{}') as "country",
coalesce(array_agg("duration"), '{}') as "duration",
coalesce(array_agg("id"), '{}') as "id",
coalesce(array_agg("visibility"), '{}') as "visibility",
coalesce(array_agg("isFavorite"), '{}') as "isFavorite",
coalesce(array_agg("isImage"), '{}') as "isImage",
coalesce(array_agg("isTrashed"), '{}') as "isTrashed",
coalesce(array_agg("livePhotoVideoId"), '{}') as "livePhotoVideoId",
coalesce(array_agg("fileCreatedAt"), '{}') as "fileCreatedAt",
coalesce(array_agg("localOffsetHours"), '{}') as "localOffsetHours",
coalesce(array_agg("ownerId"), '{}') as "ownerId",
coalesce(array_agg("projectionType"), '{}') as "projectionType",
coalesce(array_agg("ratio"), '{}') as "ratio",
coalesce(array_agg("status"), '{}') as "status",
coalesce(array_agg("thumbhash"), '{}') as "thumbhash",
coalesce(json_agg("stack"), '[]') as "stack"
from
"cte"
)
select
to_json(agg)::text as "assets"
from
"agg"
-- AssetRepository.getAssetIdByCity
with
"cities" as (
select
"city"
from
"asset_exif"
where
"city" is not null
group by
"city"
having
count("assetId") >= $1
)
select distinct
on ("asset_exif"."city") "assetId" as "data",
"asset_exif"."city" as "value"
from
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
inner join "cities" on "asset_exif"."city" = "cities"."city"
where
"ownerId" = $2::uuid
and "visibility" = $3
and "type" = $4
and "deletedAt" is null
limit
$5
-- AssetRepository.getAllForUserFullSync
select
"asset".*,
to_json("asset_exif") as "exifInfo",
to_json("stacked_assets") as "stack"
from
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join "stack" on "stack"."id" = "asset"."stackId"
left join lateral (
select
"stack".*,
count("stacked") as "assetCount"
from
"asset" as "stacked"
where
"stacked"."stackId" = "stack"."id"
group by
"stack"."id"
) as "stacked_assets" on "stack"."id" is not null
where
"asset"."ownerId" = $1::uuid
and "asset"."visibility" != $2
and "asset"."updatedAt" <= $3
and "asset"."id" > $4
order by
"asset"."id"
limit
$5
-- AssetRepository.getChangedDeltaSync
select
"asset".*,
to_json("asset_exif") as "exifInfo",
to_json("stacked_assets") as "stack"
from
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join "stack" on "stack"."id" = "asset"."stackId"
left join lateral (
select
"stack".*,
count("stacked") as "assetCount"
from
"asset" as "stacked"
where
"stacked"."stackId" = "stack"."id"
group by
"stack"."id"
) as "stacked_assets" on "stack"."id" is not null
where
"asset"."ownerId" = any ($1::uuid[])
and "asset"."visibility" != $2
and "asset"."updatedAt" > $3
limit
$4
-- AssetRepository.detectOfflineExternalAssets
update "asset"
set
"isOffline" = $1,
"deletedAt" = $2
where
"isOffline" = $3
and "isExternal" = $4
and "libraryId" = $5::uuid
and (
not "originalPath" like $6
or "originalPath" like $7
)
-- AssetRepository.filterNewExternalAssetPaths
select
"path"
from
unnest(array[$1]::text[]) as "path"
where
not exists (
select
"originalPath"
from
"asset"
where
"asset"."originalPath" = "path"
and "libraryId" = $2::uuid
and "isExternal" = $3
)