feat: rename schema (#19891)

This commit is contained in:
Jason Rasmussen 2025-07-14 10:13:06 -04:00 committed by GitHub
parent 33c29e4305
commit c699df002a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
103 changed files with 4378 additions and 3224 deletions

View File

@ -20,7 +20,7 @@ describe('/api-keys', () => {
});
beforeEach(async () => {
await utils.resetDatabase(['api_keys']);
await utils.resetDatabase(['api_key']);
});
describe('POST /api-keys', () => {

View File

@ -37,7 +37,7 @@ describe('/tags', () => {
beforeEach(async () => {
// tagging assets eventually triggers metadata extraction which can impact other tests
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
await utils.resetDatabase(['tags']);
await utils.resetDatabase(['tag']);
});
describe('POST /tags', () => {

View File

@ -97,7 +97,7 @@ describe(`immich upload`, () => {
});
beforeEach(async () => {
await utils.resetDatabase(['assets', 'albums']);
await utils.resetDatabase(['asset', 'album']);
});
describe(`immich upload /path/to/file.jpg`, () => {

View File

@ -154,19 +154,19 @@ export const utils = {
tables = tables || [
// TODO e2e test for deleting a stack, since it is quite complex
'asset_stack',
'libraries',
'shared_links',
'stack',
'library',
'shared_link',
'person',
'albums',
'assets',
'asset_faces',
'album',
'asset',
'asset_face',
'activity',
'api_keys',
'sessions',
'users',
'api_key',
'session',
'user',
'system_metadata',
'tags',
'tag',
];
const sql: string[] = [];
@ -175,7 +175,7 @@ export const utils = {
if (table === 'system_metadata') {
sql.push(`DELETE FROM "system_metadata" where "key" NOT IN ('reverse-geocoding-state', 'system-flags');`);
} else {
sql.push(`DELETE FROM ${table} CASCADE;`);
sql.push(`DELETE FROM "${table}" CASCADE;`);
}
}
@ -451,7 +451,7 @@ export const utils = {
return;
}
await client.query('INSERT INTO asset_faces ("assetId", "personId") VALUES ($1, $2)', [assetId, personId]);
await client.query('INSERT INTO asset_face ("assetId", "personId") VALUES ($1, $2)', [assetId, personId]);
},
setPersonThumbnail: async (personId: string) => {

View File

@ -9,13 +9,7 @@ import { ConfigRepository } from 'src/repositories/config.repository';
import { DatabaseRepository } from 'src/repositories/database.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import 'src/schema';
import {
DefaultNamingStrategy,
HashNamingStrategy,
schemaDiff,
schemaFromCode,
schemaFromDatabase,
} from 'src/sql-tools';
import { schemaDiff, schemaFromCode, schemaFromDatabase } from 'src/sql-tools';
import { asPostgresConnectionConfig, getKyselyConfig } from 'src/utils/database';
const main = async () => {
@ -113,22 +107,7 @@ const compare = async () => {
const { database } = configRepository.getEnv();
const db = postgres(asPostgresConnectionConfig(database.config));
const tables = new Set<string>();
const preferred = new DefaultNamingStrategy();
const fallback = new HashNamingStrategy();
const source = schemaFromCode({
overrides: true,
namingStrategy: {
getName(item) {
if ('tableName' in item && tables.has(item.tableName)) {
return preferred.getName(item);
}
return fallback.getName(item);
},
},
});
const source = schemaFromCode({ overrides: true, namingStrategy: 'default' });
const target = await schemaFromDatabase(db, {});
console.log(source.warnings.join('\n'));

View File

@ -13,7 +13,7 @@ import {
UserStatus,
} from 'src/enum';
import { AlbumTable } from 'src/schema/tables/album.table';
import { ExifTable } from 'src/schema/tables/exif.table';
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { UserMetadataItem } from 'src/types';
export type AuthUser = {
@ -242,7 +242,7 @@ export type Session = {
isPendingSyncReset: boolean;
};
export type Exif = Omit<Selectable<ExifTable>, 'updatedAt' | 'updateId'>;
export type Exif = Omit<Selectable<AssetExifTable>, 'updatedAt' | 'updateId'>;
export type Person = {
createdAt: Date;
@ -276,52 +276,45 @@ export type AssetFace = {
const userColumns = ['id', 'name', 'email', 'avatarColor', 'profileImagePath', 'profileChangedAt'] as const;
const userWithPrefixColumns = [
'users.id',
'users.name',
'users.email',
'users.avatarColor',
'users.profileImagePath',
'users.profileChangedAt',
'user2.id',
'user2.name',
'user2.email',
'user2.avatarColor',
'user2.profileImagePath',
'user2.profileChangedAt',
] as const;
export const columns = {
asset: [
'assets.id',
'assets.checksum',
'assets.deviceAssetId',
'assets.deviceId',
'assets.fileCreatedAt',
'assets.fileModifiedAt',
'assets.isExternal',
'assets.visibility',
'assets.libraryId',
'assets.livePhotoVideoId',
'assets.localDateTime',
'assets.originalFileName',
'assets.originalPath',
'assets.ownerId',
'assets.sidecarPath',
'assets.type',
'asset.id',
'asset.checksum',
'asset.deviceAssetId',
'asset.deviceId',
'asset.fileCreatedAt',
'asset.fileModifiedAt',
'asset.isExternal',
'asset.visibility',
'asset.libraryId',
'asset.livePhotoVideoId',
'asset.localDateTime',
'asset.originalFileName',
'asset.originalPath',
'asset.ownerId',
'asset.sidecarPath',
'asset.type',
],
assetFiles: ['asset_files.id', 'asset_files.path', 'asset_files.type'],
authUser: [
'users.id',
'users.name',
'users.email',
'users.isAdmin',
'users.quotaUsageInBytes',
'users.quotaSizeInBytes',
],
authApiKey: ['api_keys.id', 'api_keys.permissions'],
authSession: ['sessions.id', 'sessions.isPendingSyncReset', 'sessions.updatedAt', 'sessions.pinExpiresAt'],
assetFiles: ['asset_file.id', 'asset_file.path', 'asset_file.type'],
authUser: ['user.id', 'user.name', 'user.email', 'user.isAdmin', 'user.quotaUsageInBytes', 'user.quotaSizeInBytes'],
authApiKey: ['api_key.id', 'api_key.permissions'],
authSession: ['session.id', 'session.isPendingSyncReset', 'session.updatedAt', 'session.pinExpiresAt'],
authSharedLink: [
'shared_links.id',
'shared_links.userId',
'shared_links.expiresAt',
'shared_links.showExif',
'shared_links.allowUpload',
'shared_links.allowDownload',
'shared_links.password',
'shared_link.id',
'shared_link.userId',
'shared_link.expiresAt',
'shared_link.showExif',
'shared_link.allowUpload',
'shared_link.allowDownload',
'shared_link.password',
],
user: userColumns,
userWithPrefix: userWithPrefixColumns,
@ -339,89 +332,83 @@ export const columns = {
'quotaSizeInBytes',
'quotaUsageInBytes',
],
tag: ['tags.id', 'tags.value', 'tags.createdAt', 'tags.updatedAt', 'tags.color', 'tags.parentId'],
tag: ['tag.id', 'tag.value', 'tag.createdAt', 'tag.updatedAt', 'tag.color', 'tag.parentId'],
apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'],
notification: ['id', 'createdAt', 'level', 'type', 'title', 'description', 'data', 'readAt'],
syncAsset: [
'assets.id',
'assets.ownerId',
'assets.originalFileName',
'assets.thumbhash',
'assets.checksum',
'assets.fileCreatedAt',
'assets.fileModifiedAt',
'assets.localDateTime',
'assets.type',
'assets.deletedAt',
'assets.isFavorite',
'assets.visibility',
'assets.duration',
],
syncAlbumUser: ['album_users.albumsId as albumId', 'album_users.usersId as userId', 'album_users.role'],
syncStack: [
'asset_stack.id',
'asset_stack.createdAt',
'asset_stack.updatedAt',
'asset_stack.primaryAssetId',
'asset_stack.ownerId',
'asset.id',
'asset.ownerId',
'asset.originalFileName',
'asset.thumbhash',
'asset.checksum',
'asset.fileCreatedAt',
'asset.fileModifiedAt',
'asset.localDateTime',
'asset.type',
'asset.deletedAt',
'asset.isFavorite',
'asset.visibility',
'asset.duration',
],
syncAlbumUser: ['album_user.albumsId as albumId', 'album_user.usersId as userId', 'album_user.role'],
syncStack: ['stack.id', 'stack.createdAt', 'stack.updatedAt', 'stack.primaryAssetId', 'stack.ownerId'],
stack: ['stack.id', 'stack.primaryAssetId', 'ownerId'],
syncAssetExif: [
'exif.assetId',
'exif.description',
'exif.exifImageWidth',
'exif.exifImageHeight',
'exif.fileSizeInByte',
'exif.orientation',
'exif.dateTimeOriginal',
'exif.modifyDate',
'exif.timeZone',
'exif.latitude',
'exif.longitude',
'exif.projectionType',
'exif.city',
'exif.state',
'exif.country',
'exif.make',
'exif.model',
'exif.lensModel',
'exif.fNumber',
'exif.focalLength',
'exif.iso',
'exif.exposureTime',
'exif.profileDescription',
'exif.rating',
'exif.fps',
'asset_exif.assetId',
'asset_exif.description',
'asset_exif.exifImageWidth',
'asset_exif.exifImageHeight',
'asset_exif.fileSizeInByte',
'asset_exif.orientation',
'asset_exif.dateTimeOriginal',
'asset_exif.modifyDate',
'asset_exif.timeZone',
'asset_exif.latitude',
'asset_exif.longitude',
'asset_exif.projectionType',
'asset_exif.city',
'asset_exif.state',
'asset_exif.country',
'asset_exif.make',
'asset_exif.model',
'asset_exif.lensModel',
'asset_exif.fNumber',
'asset_exif.focalLength',
'asset_exif.iso',
'asset_exif.exposureTime',
'asset_exif.profileDescription',
'asset_exif.rating',
'asset_exif.fps',
],
exif: [
'exif.assetId',
'exif.autoStackId',
'exif.bitsPerSample',
'exif.city',
'exif.colorspace',
'exif.country',
'exif.dateTimeOriginal',
'exif.description',
'exif.exifImageHeight',
'exif.exifImageWidth',
'exif.exposureTime',
'exif.fileSizeInByte',
'exif.fNumber',
'exif.focalLength',
'exif.fps',
'exif.iso',
'exif.latitude',
'exif.lensModel',
'exif.livePhotoCID',
'exif.longitude',
'exif.make',
'exif.model',
'exif.modifyDate',
'exif.orientation',
'exif.profileDescription',
'exif.projectionType',
'exif.rating',
'exif.state',
'exif.timeZone',
'asset_exif.assetId',
'asset_exif.autoStackId',
'asset_exif.bitsPerSample',
'asset_exif.city',
'asset_exif.colorspace',
'asset_exif.country',
'asset_exif.dateTimeOriginal',
'asset_exif.description',
'asset_exif.exifImageHeight',
'asset_exif.exifImageWidth',
'asset_exif.exposureTime',
'asset_exif.fileSizeInByte',
'asset_exif.fNumber',
'asset_exif.focalLength',
'asset_exif.fps',
'asset_exif.iso',
'asset_exif.latitude',
'asset_exif.lensModel',
'asset_exif.livePhotoCID',
'asset_exif.longitude',
'asset_exif.make',
'asset_exif.model',
'asset_exif.modifyDate',
'asset_exif.orientation',
'asset_exif.profileDescription',
'asset_exif.projectionType',
'asset_exif.rating',
'asset_exif.state',
'asset_exif.timeZone',
],
} as const;

View File

@ -14,161 +14,161 @@ select
"activity"."id"
from
"activity"
left join "albums" on "activity"."albumId" = "albums"."id"
and "albums"."deletedAt" is null
left join "album" on "activity"."albumId" = "album"."id"
and "album"."deletedAt" is null
where
"activity"."id" in ($1)
and "albums"."ownerId" = $2::uuid
and "album"."ownerId" = $2::uuid
-- AccessRepository.activity.checkCreateAccess
select
"albums"."id"
"album"."id"
from
"albums"
left join "albums_shared_users_users" as "albumUsers" on "albumUsers"."albumsId" = "albums"."id"
left join "users" on "users"."id" = "albumUsers"."usersId"
and "users"."deletedAt" is null
"album"
left join "album_user" as "albumUsers" on "albumUsers"."albumsId" = "album"."id"
left join "user" on "user"."id" = "albumUsers"."usersId"
and "user"."deletedAt" is null
where
"albums"."id" in ($1)
and "albums"."isActivityEnabled" = $2
"album"."id" in ($1)
and "album"."isActivityEnabled" = $2
and (
"albums"."ownerId" = $3
or "users"."id" = $4
"album"."ownerId" = $3
or "user"."id" = $4
)
and "albums"."deletedAt" is null
and "album"."deletedAt" is null
-- AccessRepository.album.checkOwnerAccess
select
"albums"."id"
"album"."id"
from
"albums"
"album"
where
"albums"."id" in ($1)
and "albums"."ownerId" = $2
and "albums"."deletedAt" is null
"album"."id" in ($1)
and "album"."ownerId" = $2
and "album"."deletedAt" is null
-- AccessRepository.album.checkSharedAlbumAccess
select
"albums"."id"
"album"."id"
from
"albums"
left join "albums_shared_users_users" as "albumUsers" on "albumUsers"."albumsId" = "albums"."id"
left join "users" on "users"."id" = "albumUsers"."usersId"
and "users"."deletedAt" is null
"album"
left join "album_user" on "album_user"."albumsId" = "album"."id"
left join "user" on "user"."id" = "album_user"."usersId"
and "user"."deletedAt" is null
where
"albums"."id" in ($1)
and "albums"."deletedAt" is null
and "users"."id" = $2
and "albumUsers"."role" in ($3, $4)
"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_links"."albumId"
"shared_link"."albumId"
from
"shared_links"
"shared_link"
where
"shared_links"."id" = $1
and "shared_links"."albumId" in ($2)
"shared_link"."id" = $1
and "shared_link"."albumId" in ($2)
-- AccessRepository.asset.checkAlbumAccess
select
"assets"."id",
"assets"."livePhotoVideoId"
"asset"."id",
"asset"."livePhotoVideoId"
from
"albums"
inner join "albums_assets_assets" as "albumAssets" on "albums"."id" = "albumAssets"."albumsId"
inner join "assets" on "assets"."id" = "albumAssets"."assetsId"
and "assets"."deletedAt" is null
left join "albums_shared_users_users" as "albumUsers" on "albumUsers"."albumsId" = "albums"."id"
left join "users" on "users"."id" = "albumUsers"."usersId"
and "users"."deletedAt" is null
"album"
inner join "album_asset" as "albumAssets" on "album"."id" = "albumAssets"."albumsId"
inner join "asset" on "asset"."id" = "albumAssets"."assetsId"
and "asset"."deletedAt" is null
left join "album_user" as "albumUsers" on "albumUsers"."albumsId" = "album"."id"
left join "user" on "user"."id" = "albumUsers"."usersId"
and "user"."deletedAt" is null
where
array["assets"."id", "assets"."livePhotoVideoId"] && array[$1]::uuid[]
array["asset"."id", "asset"."livePhotoVideoId"] && array[$1]::uuid[]
and (
"albums"."ownerId" = $2
or "users"."id" = $3
"album"."ownerId" = $2
or "user"."id" = $3
)
and "albums"."deletedAt" is null
and "album"."deletedAt" is null
-- AccessRepository.asset.checkOwnerAccess
select
"assets"."id"
"asset"."id"
from
"assets"
"asset"
where
"assets"."id" in ($1)
and "assets"."ownerId" = $2
and "assets"."visibility" != $3
"asset"."id" in ($1)
and "asset"."ownerId" = $2
and "asset"."visibility" != $3
-- AccessRepository.asset.checkPartnerAccess
select
"assets"."id"
"asset"."id"
from
"partners" as "partner"
inner join "users" as "sharedBy" on "sharedBy"."id" = "partner"."sharedById"
"partner"
inner join "user" as "sharedBy" on "sharedBy"."id" = "partner"."sharedById"
and "sharedBy"."deletedAt" is null
inner join "assets" on "assets"."ownerId" = "sharedBy"."id"
and "assets"."deletedAt" is null
inner join "asset" on "asset"."ownerId" = "sharedBy"."id"
and "asset"."deletedAt" is null
where
"partner"."sharedWithId" = $1
and (
"assets"."visibility" = 'timeline'
or "assets"."visibility" = 'hidden'
"asset"."visibility" = 'timeline'
or "asset"."visibility" = 'hidden'
)
and "assets"."id" in ($2)
and "asset"."id" in ($2)
-- AccessRepository.asset.checkSharedLinkAccess
select
"assets"."id" as "assetId",
"assets"."livePhotoVideoId" as "assetLivePhotoVideoId",
"asset"."id" as "assetId",
"asset"."livePhotoVideoId" as "assetLivePhotoVideoId",
"albumAssets"."id" as "albumAssetId",
"albumAssets"."livePhotoVideoId" as "albumAssetLivePhotoVideoId"
from
"shared_links"
left join "albums" on "albums"."id" = "shared_links"."albumId"
and "albums"."deletedAt" is null
left join "shared_link__asset" on "shared_link__asset"."sharedLinksId" = "shared_links"."id"
left join "assets" on "assets"."id" = "shared_link__asset"."assetsId"
and "assets"."deletedAt" is null
left join "albums_assets_assets" on "albums_assets_assets"."albumsId" = "albums"."id"
left join "assets" as "albumAssets" on "albumAssets"."id" = "albums_assets_assets"."assetsId"
"shared_link"
left join "album" on "album"."id" = "shared_link"."albumId"
and "album"."deletedAt" is null
left join "shared_link_asset" on "shared_link_asset"."sharedLinksId" = "shared_link"."id"
left join "asset" on "asset"."id" = "shared_link_asset"."assetsId"
and "asset"."deletedAt" is null
left join "album_asset" on "album_asset"."albumsId" = "album"."id"
left join "asset" as "albumAssets" on "albumAssets"."id" = "album_asset"."assetsId"
and "albumAssets"."deletedAt" is null
where
"shared_links"."id" = $1
"shared_link"."id" = $1
and array[
"assets"."id",
"assets"."livePhotoVideoId",
"asset"."id",
"asset"."livePhotoVideoId",
"albumAssets"."id",
"albumAssets"."livePhotoVideoId"
] && array[$2]::uuid[]
-- AccessRepository.authDevice.checkOwnerAccess
select
"sessions"."id"
"session"."id"
from
"sessions"
"session"
where
"sessions"."userId" = $1
and "sessions"."id" in ($2)
"session"."userId" = $1
and "session"."id" in ($2)
-- AccessRepository.memory.checkOwnerAccess
select
"memories"."id"
"memory"."id"
from
"memories"
"memory"
where
"memories"."id" in ($1)
and "memories"."ownerId" = $2
and "memories"."deletedAt" is null
"memory"."id" in ($1)
and "memory"."ownerId" = $2
and "memory"."deletedAt" is null
-- AccessRepository.notification.checkOwnerAccess
select
"notifications"."id"
"notification"."id"
from
"notifications"
"notification"
where
"notifications"."id" in ($1)
and "notifications"."userId" = $2
"notification"."id" in ($1)
and "notification"."userId" = $2
-- AccessRepository.person.checkOwnerAccess
select
@ -181,56 +181,56 @@ where
-- AccessRepository.person.checkFaceOwnerAccess
select
"asset_faces"."id"
"asset_face"."id"
from
"asset_faces"
left join "assets" on "assets"."id" = "asset_faces"."assetId"
and "assets"."deletedAt" is null
"asset_face"
left join "asset" on "asset"."id" = "asset_face"."assetId"
and "asset"."deletedAt" is null
where
"asset_faces"."id" in ($1)
and "assets"."ownerId" = $2
"asset_face"."id" in ($1)
and "asset"."ownerId" = $2
-- AccessRepository.partner.checkUpdateAccess
select
"partners"."sharedById"
"partner"."sharedById"
from
"partners"
"partner"
where
"partners"."sharedById" in ($1)
and "partners"."sharedWithId" = $2
"partner"."sharedById" in ($1)
and "partner"."sharedWithId" = $2
-- AccessRepository.session.checkOwnerAccess
select
"sessions"."id"
"session"."id"
from
"sessions"
"session"
where
"sessions"."id" in ($1)
and "sessions"."userId" = $2
"session"."id" in ($1)
and "session"."userId" = $2
-- AccessRepository.stack.checkOwnerAccess
select
"stacks"."id"
"stack"."id"
from
"asset_stack" as "stacks"
"stack"
where
"stacks"."id" in ($1)
and "stacks"."ownerId" = $2
"stack"."id" in ($1)
and "stack"."ownerId" = $2
-- AccessRepository.tag.checkOwnerAccess
select
"tags"."id"
"tag"."id"
from
"tags"
"tag"
where
"tags"."id" in ($1)
and "tags"."userId" = $2
"tag"."id" in ($1)
and "tag"."userId" = $2
-- AccessRepository.timeline.checkPartnerAccess
select
"partners"."sharedById"
"partner"."sharedById"
from
"partners"
"partner"
where
"partners"."sharedById" in ($1)
and "partners"."sharedWithId" = $2
"partner"."sharedById" in ($1)
and "partner"."sharedWithId" = $2

View File

@ -6,26 +6,26 @@ select
to_json("user") as "user"
from
"activity"
inner join "users" on "users"."id" = "activity"."userId"
and "users"."deletedAt" is null
inner join "user" as "user2" on "user2"."id" = "activity"."userId"
and "user2"."deletedAt" is null
inner join lateral (
select
"users"."id",
"users"."name",
"users"."email",
"users"."avatarColor",
"users"."profileImagePath",
"users"."profileChangedAt"
"user2"."id",
"user2"."name",
"user2"."email",
"user2"."avatarColor",
"user2"."profileImagePath",
"user2"."profileChangedAt"
from
(
select
1
) as "dummy"
) as "user" on true
left join "assets" on "assets"."id" = "activity"."assetId"
left join "asset" on "asset"."id" = "activity"."assetId"
where
"activity"."albumId" = $1
and "assets"."deletedAt" is null
and "asset"."deletedAt" is null
order by
"activity"."createdAt" asc
@ -49,9 +49,9 @@ returning
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "activity"."userId"
"user"."id" = "activity"."userId"
) as obj
) as "user"
@ -72,16 +72,16 @@ select
) as "likes"
from
"activity"
inner join "users" on "users"."id" = "activity"."userId"
and "users"."deletedAt" is null
left join "assets" on "assets"."id" = "activity"."assetId"
inner join "user" on "user"."id" = "activity"."userId"
and "user"."deletedAt" is null
left join "asset" on "asset"."id" = "activity"."assetId"
where
"activity"."assetId" = $3
and "activity"."albumId" = $4
and (
(
"assets"."deletedAt" is null
and "assets"."visibility" != 'locked'
"asset"."deletedAt" is null
and "asset"."visibility" != 'locked'
)
or "assets"."id" is null
or "asset"."id" is null
)

View File

@ -2,7 +2,7 @@
-- AlbumRepository.getById
select
"albums".*,
"album".*,
(
select
to_json(obj)
@ -16,9 +16,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
"user"."id" = "album"."ownerId"
) as obj
) as "owner",
(
@ -27,7 +27,7 @@ select
from
(
select
"album_users"."role",
"album_user"."role",
(
select
to_json(obj)
@ -41,15 +41,15 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "album_users"."usersId"
"user"."id" = "album_user"."usersId"
) as obj
) as "user"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
) as agg
) as "albumUsers",
(
@ -60,9 +60,9 @@ select
select
*
from
"shared_links"
"shared_link"
where
"shared_links"."albumId" = "albums"."id"
"shared_link"."albumId" = "album"."id"
) as agg
) as "sharedLinks",
(
@ -71,29 +71,29 @@ select
from
(
select
"assets".*,
"exif" as "exifInfo"
"asset".*,
"asset_exif" as "exifInfo"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
inner join "albums_assets_assets" on "albums_assets_assets"."assetsId" = "assets"."id"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
inner join "album_asset" on "album_asset"."assetsId" = "asset"."id"
where
"albums_assets_assets"."albumsId" = "albums"."id"
and "assets"."deletedAt" is null
and "assets"."visibility" in ('archive', 'timeline')
"album_asset"."albumsId" = "album"."id"
and "asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
order by
"assets"."fileCreatedAt" desc
"asset"."fileCreatedAt" desc
) as "asset"
) as "assets"
from
"albums"
"album"
where
"albums"."id" = $1
and "albums"."deletedAt" is null
"album"."id" = $1
and "album"."deletedAt" is null
-- AlbumRepository.getByAssetId
select
"albums".*,
"album".*,
(
select
to_json(obj)
@ -107,9 +107,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
"user"."id" = "album"."ownerId"
) as obj
) as "owner",
(
@ -118,7 +118,7 @@ select
from
(
select
"album_users"."role",
"album_user"."role",
(
select
to_json(obj)
@ -132,62 +132,62 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "album_users"."usersId"
"user"."id" = "album_user"."usersId"
) as obj
) as "user"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
) as agg
) as "albumUsers"
from
"albums"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."albumsId" = "albums"."id"
"album"
inner join "album_asset" on "album_asset"."albumsId" = "album"."id"
where
(
"albums"."ownerId" = $1
"album"."ownerId" = $1
or exists (
select
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
and "album_users"."usersId" = $2
"album_user"."albumsId" = "album"."id"
and "album_user"."usersId" = $2
)
)
and "album_assets"."assetsId" = $3
and "albums"."deletedAt" is null
and "album_asset"."assetsId" = $3
and "album"."deletedAt" is null
order by
"albums"."createdAt" desc,
"albums"."createdAt" desc
"album"."createdAt" desc,
"album"."createdAt" desc
-- AlbumRepository.getMetadataForIds
select
"album_assets"."albumsId" as "albumId",
"album_asset"."albumsId" as "albumId",
min(
("assets"."localDateTime" AT TIME ZONE 'UTC'::text)::date
("asset"."localDateTime" AT TIME ZONE 'UTC'::text)::date
) as "startDate",
max(
("assets"."localDateTime" AT TIME ZONE 'UTC'::text)::date
("asset"."localDateTime" AT TIME ZONE 'UTC'::text)::date
) as "endDate",
max("assets"."updatedAt") as "lastModifiedAssetTimestamp",
count("assets"."id")::int as "assetCount"
max("asset"."updatedAt") as "lastModifiedAssetTimestamp",
count("asset"."id")::int as "assetCount"
from
"assets"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."assetsId" = "assets"."id"
"asset"
inner join "album_asset" on "album_asset"."assetsId" = "asset"."id"
where
"assets"."visibility" in ('archive', 'timeline')
and "album_assets"."albumsId" in ($1)
and "assets"."deletedAt" is null
"asset"."visibility" in ('archive', 'timeline')
and "album_asset"."albumsId" in ($1)
and "asset"."deletedAt" is null
group by
"album_assets"."albumsId"
"album_asset"."albumsId"
-- AlbumRepository.getOwned
select
"albums".*,
"album".*,
(
select
to_json(obj)
@ -201,9 +201,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
"user"."id" = "album"."ownerId"
) as obj
) as "owner",
(
@ -212,7 +212,7 @@ select
from
(
select
"album_users"."role",
"album_user"."role",
(
select
to_json(obj)
@ -226,15 +226,15 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "album_users"."usersId"
"user"."id" = "album_user"."usersId"
) as obj
) as "user"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
) as agg
) as "albumUsers",
(
@ -245,29 +245,29 @@ select
select
*
from
"shared_links"
"shared_link"
where
"shared_links"."albumId" = "albums"."id"
"shared_link"."albumId" = "album"."id"
) as agg
) as "sharedLinks"
from
"albums"
"album"
where
"albums"."ownerId" = $1
and "albums"."deletedAt" is null
"album"."ownerId" = $1
and "album"."deletedAt" is null
order by
"albums"."createdAt" desc
"album"."createdAt" desc
-- AlbumRepository.getShared
select
"albums".*,
"album".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"album_users"."role",
"album_user"."role",
(
select
to_json(obj)
@ -281,15 +281,15 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "album_users"."usersId"
"user"."id" = "album_user"."usersId"
) as obj
) as "user"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
) as agg
) as "albumUsers",
(
@ -305,9 +305,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
"user"."id" = "album"."ownerId"
) as obj
) as "owner",
(
@ -318,42 +318,42 @@ select
select
*
from
"shared_links"
"shared_link"
where
"shared_links"."albumId" = "albums"."id"
"shared_link"."albumId" = "album"."id"
) as agg
) as "sharedLinks"
from
"albums"
"album"
where
(
exists (
select
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
and (
"albums"."ownerId" = $1
or "album_users"."usersId" = $2
"album"."ownerId" = $1
or "album_user"."usersId" = $2
)
)
or exists (
select
from
"shared_links"
"shared_link"
where
"shared_links"."albumId" = "albums"."id"
and "shared_links"."userId" = $3
"shared_link"."albumId" = "album"."id"
and "shared_link"."userId" = $3
)
)
and "albums"."deletedAt" is null
and "album"."deletedAt" is null
order by
"albums"."createdAt" desc
"album"."createdAt" desc
-- AlbumRepository.getNotShared
select
"albums".*,
"album".*,
(
select
to_json(obj)
@ -367,43 +367,43 @@ select
"profileImagePath",
"profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
"user"."id" = "album"."ownerId"
) as obj
) as "owner"
from
"albums"
"album"
where
"albums"."ownerId" = $1
and "albums"."deletedAt" is null
"album"."ownerId" = $1
and "album"."deletedAt" is null
and not exists (
select
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."albumsId" = "albums"."id"
"album_user"."albumsId" = "album"."id"
)
and not exists (
select
from
"shared_links"
"shared_link"
where
"shared_links"."albumId" = "albums"."id"
"shared_link"."albumId" = "album"."id"
)
order by
"albums"."createdAt" desc
"album"."createdAt" desc
-- AlbumRepository.removeAssetsFromAll
delete from "albums_assets_assets"
delete from "album_asset"
where
"albums_assets_assets"."assetsId" in ($1)
"album_asset"."assetsId" in ($1)
-- AlbumRepository.getAssetIds
select
*
from
"albums_assets_assets"
"album_asset"
where
"albums_assets_assets"."albumsId" = $1
and "albums_assets_assets"."assetsId" in ($2)
"album_asset"."albumsId" = $1
and "album_asset"."assetsId" in ($2)

View File

@ -2,7 +2,7 @@
-- AlbumUserRepository.create
insert into
"albums_shared_users_users" ("usersId", "albumsId")
"album_user" ("usersId", "albumsId")
values
($1, $2)
returning
@ -11,7 +11,7 @@ returning
"role"
-- AlbumUserRepository.update
update "albums_shared_users_users"
update "album_user"
set
"role" = $1
where
@ -21,7 +21,7 @@ returning
*
-- AlbumUserRepository.delete
delete from "albums_shared_users_users"
delete from "album_user"
where
"usersId" = $1
and "albumsId" = $2

View File

@ -2,31 +2,31 @@
-- ApiKeyRepository.getKey
select
"api_keys"."id",
"api_keys"."permissions",
"api_key"."id",
"api_key"."permissions",
(
select
to_json(obj)
from
(
select
"users"."id",
"users"."name",
"users"."email",
"users"."isAdmin",
"users"."quotaUsageInBytes",
"users"."quotaSizeInBytes"
"user"."id",
"user"."name",
"user"."email",
"user"."isAdmin",
"user"."quotaUsageInBytes",
"user"."quotaSizeInBytes"
from
"users"
"user"
where
"users"."id" = "api_keys"."userId"
and "users"."deletedAt" is null
"user"."id" = "api_key"."userId"
and "user"."deletedAt" is null
) as obj
) as "user"
from
"api_keys"
"api_key"
where
"api_keys"."key" = $1
"api_key"."key" = $1
-- ApiKeyRepository.getById
select
@ -37,7 +37,7 @@ select
"updatedAt",
"permissions"
from
"api_keys"
"api_key"
where
"id" = $1::uuid
and "userId" = $2
@ -51,7 +51,7 @@ select
"updatedAt",
"permissions"
from
"api_keys"
"api_key"
where
"userId" = $1
order by

View File

@ -10,10 +10,10 @@ select
"visibility",
"smart_search"."embedding"
from
"assets"
left join "smart_search" on "assets"."id" = "smart_search"."assetId"
"asset"
left join "smart_search" on "asset"."id" = "smart_search"."assetId"
where
"assets"."id" = $1::uuid
"asset"."id" = $1::uuid
limit
$2
@ -28,227 +28,227 @@ select
from
(
select
"tags"."value"
"tag"."value"
from
"tags"
inner join "tag_asset" on "tags"."id" = "tag_asset"."tagsId"
"tag"
inner join "tag_asset" on "tag"."id" = "tag_asset"."tagsId"
where
"assets"."id" = "tag_asset"."assetsId"
"asset"."id" = "tag_asset"."assetsId"
) as agg
) as "tags"
from
"assets"
"asset"
where
"assets"."id" = $1::uuid
"asset"."id" = $1::uuid
limit
$2
-- AssetJobRepository.streamForThumbnailJob
select
"assets"."id",
"assets"."thumbhash",
"asset"."id",
"asset"."thumbhash",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
"asset_file"."assetId" = "asset"."id"
) as agg
) as "files"
from
"assets"
inner join "asset_job_status" on "asset_job_status"."assetId" = "assets"."id"
"asset"
inner join "asset_job_status" on "asset_job_status"."assetId" = "asset"."id"
where
"assets"."deletedAt" is null
and "assets"."visibility" != $1
"asset"."deletedAt" is null
and "asset"."visibility" != $1
and (
"asset_job_status"."previewAt" is null
or "asset_job_status"."thumbnailAt" is null
or "assets"."thumbhash" is null
or "asset"."thumbhash" is null
)
-- AssetJobRepository.getForMigrationJob
select
"assets"."id",
"assets"."ownerId",
"assets"."encodedVideoPath",
"asset"."id",
"asset"."ownerId",
"asset"."encodedVideoPath",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
"asset_file"."assetId" = "asset"."id"
) as agg
) as "files"
from
"assets"
"asset"
where
"assets"."id" = $1
"asset"."id" = $1
-- AssetJobRepository.getForGenerateThumbnailJob
select
"assets"."id",
"assets"."visibility",
"assets"."originalFileName",
"assets"."originalPath",
"assets"."ownerId",
"assets"."thumbhash",
"assets"."type",
"asset"."id",
"asset"."visibility",
"asset"."originalFileName",
"asset"."originalPath",
"asset"."ownerId",
"asset"."thumbhash",
"asset"."type",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
"asset_file"."assetId" = "asset"."id"
) as agg
) as "files",
to_json("exif") as "exifInfo"
to_json("asset_exif") as "exifInfo"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."id" = $1
"asset"."id" = $1
-- AssetJobRepository.getForMetadataExtraction
select
"assets"."id",
"assets"."checksum",
"assets"."deviceAssetId",
"assets"."deviceId",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."isExternal",
"assets"."visibility",
"assets"."libraryId",
"assets"."livePhotoVideoId",
"assets"."localDateTime",
"assets"."originalFileName",
"assets"."originalPath",
"assets"."ownerId",
"assets"."sidecarPath",
"assets"."type",
"asset"."id",
"asset"."checksum",
"asset"."deviceAssetId",
"asset"."deviceId",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."isExternal",
"asset"."visibility",
"asset"."libraryId",
"asset"."livePhotoVideoId",
"asset"."localDateTime",
"asset"."originalFileName",
"asset"."originalPath",
"asset"."ownerId",
"asset"."sidecarPath",
"asset"."type",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_faces".*
"asset_face".*
from
"asset_faces"
"asset_face"
where
"asset_faces"."assetId" = "assets"."id"
and "asset_faces"."deletedAt" is null
"asset_face"."assetId" = "asset"."id"
and "asset_face"."deletedAt" is null
) as agg
) as "faces"
from
"assets"
"asset"
where
"assets"."id" = $1
"asset"."id" = $1
-- AssetJobRepository.getAlbumThumbnailFiles
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = $1
and "asset_files"."type" = $2
"asset_file"."assetId" = $1
and "asset_file"."type" = $2
-- AssetJobRepository.streamForSearchDuplicates
select
"assets"."id"
"asset"."id"
from
"assets"
inner join "smart_search" on "assets"."id" = "smart_search"."assetId"
inner join "asset_job_status" as "job_status" on "job_status"."assetId" = "assets"."id"
"asset"
inner join "smart_search" on "asset"."id" = "smart_search"."assetId"
inner join "asset_job_status" as "job_status" on "job_status"."assetId" = "asset"."id"
where
"assets"."deletedAt" is null
and "assets"."visibility" in ('archive', 'timeline')
"asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
and "job_status"."duplicatesDetectedAt" is null
-- AssetJobRepository.streamForEncodeClip
select
"assets"."id"
"asset"."id"
from
"assets"
inner join "asset_job_status" as "job_status" on "assetId" = "assets"."id"
"asset"
inner join "asset_job_status" as "job_status" on "assetId" = "asset"."id"
where
"assets"."visibility" != $1
and "assets"."deletedAt" is null
"asset"."visibility" != $1
and "asset"."deletedAt" is null
and "job_status"."previewAt" is not null
and not exists (
select
from
"smart_search"
where
"assetId" = "assets"."id"
"assetId" = "asset"."id"
)
-- AssetJobRepository.getForClipEncoding
select
"assets"."id",
"assets"."visibility",
"asset"."id",
"asset"."visibility",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
and "asset_files"."type" = $1
"asset_file"."assetId" = "asset"."id"
and "asset_file"."type" = $1
) as agg
) as "files"
from
"assets"
"asset"
where
"assets"."id" = $2
"asset"."id" = $2
-- AssetJobRepository.getForDetectFacesJob
select
"assets"."id",
"assets"."visibility",
to_json("exif") as "exifInfo",
"asset"."id",
"asset"."visibility",
to_json("asset_exif") as "exifInfo",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_faces".*
"asset_face".*
from
"asset_faces"
"asset_face"
where
"asset_faces"."assetId" = "assets"."id"
"asset_face"."assetId" = "asset"."id"
) as agg
) as "faces",
(
@ -257,67 +257,67 @@ select
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
and "asset_files"."type" = $1
"asset_file"."assetId" = "asset"."id"
and "asset_file"."type" = $1
) as agg
) as "files"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."id" = $2
"asset"."id" = $2
-- AssetJobRepository.getForSyncAssets
select
"assets"."id",
"assets"."isOffline",
"assets"."libraryId",
"assets"."originalPath",
"assets"."status",
"assets"."fileModifiedAt"
"asset"."id",
"asset"."isOffline",
"asset"."libraryId",
"asset"."originalPath",
"asset"."status",
"asset"."fileModifiedAt"
from
"assets"
"asset"
where
"assets"."id" = any ($1::uuid[])
"asset"."id" = any ($1::uuid[])
-- AssetJobRepository.getForAssetDeletion
select
"assets"."id",
"assets"."visibility",
"assets"."libraryId",
"assets"."ownerId",
"assets"."livePhotoVideoId",
"assets"."sidecarPath",
"assets"."encodedVideoPath",
"assets"."originalPath",
to_json("exif") as "exifInfo",
"asset"."id",
"asset"."visibility",
"asset"."libraryId",
"asset"."ownerId",
"asset"."livePhotoVideoId",
"asset"."sidecarPath",
"asset"."encodedVideoPath",
"asset"."originalPath",
to_json("asset_exif") as "exifInfo",
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_faces".*,
"asset_face".*,
"person" as "person"
from
"asset_faces"
"asset_face"
left join lateral (
select
"person".*
from
"person"
where
"asset_faces"."personId" = "person"."id"
"asset_face"."personId" = "person"."id"
) as "person" on true
where
"asset_faces"."assetId" = "assets"."id"
and "asset_faces"."deletedAt" is null
"asset_face"."assetId" = "asset"."id"
and "asset_face"."deletedAt" is null
) as agg
) as "faces",
(
@ -326,156 +326,156 @@ select
from
(
select
"asset_files"."id",
"asset_files"."path",
"asset_files"."type"
"asset_file"."id",
"asset_file"."path",
"asset_file"."type"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
"asset_file"."assetId" = "asset"."id"
) as agg
) as "files",
to_json("stacked_assets") as "stack"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
left join "asset_stack" on "asset_stack"."id" = "assets"."stackId"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join "stack" on "stack"."id" = "asset"."stackId"
left join lateral (
select
"asset_stack"."id",
"asset_stack"."primaryAssetId",
"stack"."id",
"stack"."primaryAssetId",
array_agg("stacked") as "assets"
from
"assets" as "stacked"
"asset" as "stacked"
where
"stacked"."deletedAt" is not null
and "stacked"."visibility" = $1
and "stacked"."stackId" = "asset_stack"."id"
and "stacked"."stackId" = "stack"."id"
group by
"asset_stack"."id"
) as "stacked_assets" on "asset_stack"."id" is not null
"stack"."id"
) as "stacked_assets" on "stack"."id" is not null
where
"assets"."id" = $2
"asset"."id" = $2
-- AssetJobRepository.streamForVideoConversion
select
"assets"."id"
"asset"."id"
from
"assets"
"asset"
where
"assets"."type" = $1
"asset"."type" = $1
and (
"assets"."encodedVideoPath" is null
or "assets"."encodedVideoPath" = $2
"asset"."encodedVideoPath" is null
or "asset"."encodedVideoPath" = $2
)
and "assets"."visibility" != $3
and "assets"."deletedAt" is null
and "asset"."visibility" != $3
and "asset"."deletedAt" is null
-- AssetJobRepository.getForVideoConversion
select
"assets"."id",
"assets"."ownerId",
"assets"."originalPath",
"assets"."encodedVideoPath"
"asset"."id",
"asset"."ownerId",
"asset"."originalPath",
"asset"."encodedVideoPath"
from
"assets"
"asset"
where
"assets"."id" = $1
and "assets"."type" = $2
"asset"."id" = $1
and "asset"."type" = $2
-- AssetJobRepository.streamForMetadataExtraction
select
"assets"."id"
"asset"."id"
from
"assets"
left join "asset_job_status" on "asset_job_status"."assetId" = "assets"."id"
"asset"
left join "asset_job_status" on "asset_job_status"."assetId" = "asset"."id"
where
(
"asset_job_status"."metadataExtractedAt" is null
or "asset_job_status"."assetId" is null
)
and "assets"."deletedAt" is null
and "asset"."deletedAt" is null
-- AssetJobRepository.getForStorageTemplateJob
select
"assets"."id",
"assets"."ownerId",
"assets"."type",
"assets"."checksum",
"assets"."originalPath",
"assets"."isExternal",
"assets"."sidecarPath",
"assets"."originalFileName",
"assets"."livePhotoVideoId",
"assets"."fileCreatedAt",
"exif"."timeZone",
"exif"."fileSizeInByte"
"asset"."id",
"asset"."ownerId",
"asset"."type",
"asset"."checksum",
"asset"."originalPath",
"asset"."isExternal",
"asset"."sidecarPath",
"asset"."originalFileName",
"asset"."livePhotoVideoId",
"asset"."fileCreatedAt",
"asset_exif"."timeZone",
"asset_exif"."fileSizeInByte"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."deletedAt" is null
and "assets"."id" = $1
"asset"."deletedAt" is null
and "asset"."id" = $1
-- AssetJobRepository.streamForStorageTemplateJob
select
"assets"."id",
"assets"."ownerId",
"assets"."type",
"assets"."checksum",
"assets"."originalPath",
"assets"."isExternal",
"assets"."sidecarPath",
"assets"."originalFileName",
"assets"."livePhotoVideoId",
"assets"."fileCreatedAt",
"exif"."timeZone",
"exif"."fileSizeInByte"
"asset"."id",
"asset"."ownerId",
"asset"."type",
"asset"."checksum",
"asset"."originalPath",
"asset"."isExternal",
"asset"."sidecarPath",
"asset"."originalFileName",
"asset"."livePhotoVideoId",
"asset"."fileCreatedAt",
"asset_exif"."timeZone",
"asset_exif"."fileSizeInByte"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."deletedAt" is null
"asset"."deletedAt" is null
-- AssetJobRepository.streamForDeletedJob
select
"id",
"isOffline"
from
"assets"
"asset"
where
"assets"."deletedAt" <= $1
"asset"."deletedAt" <= $1
-- AssetJobRepository.streamForSidecar
select
"assets"."id"
"asset"."id"
from
"assets"
"asset"
where
(
"assets"."sidecarPath" = $1
or "assets"."sidecarPath" is null
"asset"."sidecarPath" = $1
or "asset"."sidecarPath" is null
)
and "assets"."visibility" != $2
and "asset"."visibility" != $2
-- AssetJobRepository.streamForDetectFacesJob
select
"assets"."id"
"asset"."id"
from
"assets"
inner join "asset_job_status" as "job_status" on "assetId" = "assets"."id"
"asset"
inner join "asset_job_status" as "job_status" on "assetId" = "asset"."id"
where
"assets"."visibility" != $1
and "assets"."deletedAt" is null
"asset"."visibility" != $1
and "asset"."deletedAt" is null
and "job_status"."previewAt" is not null
and "job_status"."facesRecognizedAt" is null
order by
"assets"."createdAt" desc
"asset"."createdAt" desc
-- AssetJobRepository.streamForMigrationJob
select
"id"
from
"assets"
"asset"
where
"assets"."deletedAt" is null
"asset"."deletedAt" is null

View File

@ -1,7 +1,7 @@
-- NOTE: This file is auto generated by ./sql-generator
-- AssetRepository.updateAllExif
update "exif"
update "asset_exif"
set
"model" = $1
where
@ -23,42 +23,42 @@ with
min(("localDateTime" at time zone 'UTC')::date)
)::int
from
assets
asset
),
date_part('year', current_date)::int - 1
) as "year"
)
select
"a".*,
to_json("exif") as "exifInfo"
to_json("asset_exif") as "exifInfo"
from
"today"
inner join lateral (
select
"assets".*
"asset".*
from
"assets"
inner join "asset_job_status" on "assets"."id" = "asset_job_status"."assetId"
"asset"
inner join "asset_job_status" on "asset"."id" = "asset_job_status"."assetId"
where
"asset_job_status"."previewAt" is not null
and (assets."localDateTime" at time zone 'UTC')::date = today.date
and "assets"."ownerId" = any ($3::uuid[])
and "assets"."visibility" = $4
and (asset."localDateTime" at time zone 'UTC')::date = today.date
and "asset"."ownerId" = any ($3::uuid[])
and "asset"."visibility" = $4
and exists (
select
from
"asset_files"
"asset_file"
where
"assetId" = "assets"."id"
and "asset_files"."type" = $5
"assetId" = "asset"."id"
and "asset_file"."type" = $5
)
and "assets"."deletedAt" is null
and "asset"."deletedAt" is null
order by
(assets."localDateTime" at time zone 'UTC')::date desc
(asset."localDateTime" at time zone 'UTC')::date desc
limit
$6
) as "a" on true
inner join "exif" on "a"."id" = "exif"."assetId"
inner join "asset_exif" on "a"."id" = "asset_exif"."assetId"
)
select
date_part(
@ -75,36 +75,36 @@ order by
-- AssetRepository.getByIds
select
"assets".*
"asset".*
from
"assets"
"asset"
where
"assets"."id" = any ($1::uuid[])
"asset"."id" = any ($1::uuid[])
-- AssetRepository.getByIdsWithAllRelationsButStacks
select
"assets".*,
"asset".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"asset_faces".*,
"asset_face".*,
"person" as "person"
from
"asset_faces"
"asset_face"
left join lateral (
select
"person".*
from
"person"
where
"asset_faces"."personId" = "person"."id"
"asset_face"."personId" = "person"."id"
) as "person" on true
where
"asset_faces"."assetId" = "assets"."id"
and "asset_faces"."deletedAt" is null
"asset_face"."assetId" = "asset"."id"
and "asset_face"."deletedAt" is null
) as agg
) as "faces",
(
@ -113,36 +113,36 @@ select
from
(
select
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tags"
inner join "tag_asset" on "tags"."id" = "tag_asset"."tagsId"
"tag"
inner join "tag_asset" on "tag"."id" = "tag_asset"."tagsId"
where
"assets"."id" = "tag_asset"."assetsId"
"asset"."id" = "tag_asset"."assetsId"
) as agg
) as "tags",
to_json("exif") as "exifInfo"
to_json("asset_exif") as "exifInfo"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."id" = any ($1::uuid[])
"asset"."id" = any ($1::uuid[])
-- AssetRepository.deleteAll
delete from "assets"
delete from "asset"
where
"ownerId" = $1
-- AssetRepository.getByLibraryIdAndOriginalPath
select
"assets".*
"asset".*
from
"assets"
"asset"
where
"libraryId" = $1::uuid
and "originalPath" = $2
@ -153,7 +153,7 @@ limit
select
"deviceAssetId"
from
"assets"
"asset"
where
"ownerId" = $1::uuid
and "deviceId" = $2
@ -164,22 +164,22 @@ where
select
count(*) as "count"
from
"assets"
"asset"
where
"livePhotoVideoId" = $1::uuid
-- AssetRepository.getById
select
"assets".*
"asset".*
from
"assets"
"asset"
where
"assets"."id" = $1::uuid
"asset"."id" = $1::uuid
limit
$2
-- AssetRepository.updateAll
update "assets"
update "asset"
set
"deviceId" = $1
where
@ -187,9 +187,9 @@ where
-- AssetRepository.getByChecksum
select
"assets".*
"asset".*
from
"assets"
"asset"
where
"ownerId" = $1::uuid
and "checksum" = $2
@ -203,7 +203,7 @@ select
"checksum",
"deletedAt"
from
"assets"
"asset"
where
"ownerId" = $1::uuid
and "checksum" in ($2)
@ -212,7 +212,7 @@ where
select
"id"
from
"assets"
"asset"
where
"ownerId" = $1::uuid
and "checksum" = $2
@ -222,20 +222,20 @@ limit
-- AssetRepository.getTimeBuckets
with
"assets" as (
"asset" as (
select
date_trunc('MONTH', "localDateTime" AT TIME ZONE 'UTC') AT TIME ZONE 'UTC' as "timeBucket"
from
"assets"
"asset"
where
"assets"."deletedAt" is null
and "assets"."visibility" in ('archive', 'timeline')
"asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
)
select
("timeBucket" AT TIME ZONE 'UTC')::date::text as "timeBucket",
count(*) as "count"
from
"assets"
"asset"
group by
"timeBucket"
order by
@ -245,37 +245,37 @@ order by
with
"cte" as (
select
"assets"."duration",
"assets"."id",
"assets"."visibility",
"assets"."isFavorite",
assets.type = 'IMAGE' as "isImage",
assets."deletedAt" is not null as "isTrashed",
"assets"."livePhotoVideoId",
"asset"."duration",
"asset"."id",
"asset"."visibility",
"asset"."isFavorite",
asset.type = 'IMAGE' as "isImage",
asset."deletedAt" is not null as "isTrashed",
"asset"."livePhotoVideoId",
extract(
epoch
from
(
assets."localDateTime" - assets."fileCreatedAt" at time zone 'UTC'
asset."localDateTime" - asset."fileCreatedAt" at time zone 'UTC'
)
)::real / 3600 as "localOffsetHours",
"assets"."ownerId",
"assets"."status",
assets."fileCreatedAt" at time zone 'utc' as "fileCreatedAt",
encode("assets"."thumbhash", 'base64') as "thumbhash",
"exif"."city",
"exif"."country",
"exif"."projectionType",
"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 exif."exifImageHeight" = 0
or exif."exifImageWidth" = 0 then 1
when "exif"."orientation" in ('5', '6', '7', '8', '-90', '90') then round(
exif."exifImageHeight"::numeric / exif."exifImageWidth"::numeric,
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(
exif."exifImageWidth"::numeric / exif."exifImageHeight"::numeric,
asset_exif."exifImageWidth"::numeric / asset_exif."exifImageHeight"::numeric,
3
)
end,
@ -283,34 +283,34 @@ with
) as "ratio",
"stack"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"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
"assets" as "stacked"
"asset" as "stacked"
where
"stacked"."stackId" = "assets"."stackId"
"stacked"."stackId" = "asset"."stackId"
and "stacked"."deletedAt" is null
and "stacked"."visibility" = $1
group by
"stacked"."stackId"
) as "stacked_assets" on true
where
"assets"."deletedAt" is null
and "assets"."visibility" in ('archive', 'timeline')
"asset"."deletedAt" is null
and "asset"."visibility" in ('archive', 'timeline')
and date_trunc('MONTH', "localDateTime" AT TIME ZONE 'UTC') AT TIME ZONE 'UTC' = $2
and not exists (
select
from
"asset_stack"
"stack"
where
"asset_stack"."id" = "assets"."stackId"
and "asset_stack"."primaryAssetId" != "assets"."id"
"stack"."id" = "asset"."stackId"
and "stack"."primaryAssetId" != "asset"."id"
)
order by
"assets"."fileCreatedAt" desc
"asset"."fileCreatedAt" desc
),
"agg" as (
select
@ -345,7 +345,7 @@ with
select
"city"
from
"exif"
"asset_exif"
where
"city" is not null
group by
@ -354,12 +354,12 @@ with
count("assetId") >= $1
)
select distinct
on ("exif"."city") "assetId" as "data",
"exif"."city" as "value"
on ("asset_exif"."city") "assetId" as "data",
"asset_exif"."city" as "value"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
inner join "cities" on "exif"."city" = "cities"."city"
"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
@ -370,63 +370,63 @@ limit
-- AssetRepository.getAllForUserFullSync
select
"assets".*,
to_json("exif") as "exifInfo",
"asset".*,
to_json("asset_exif") as "exifInfo",
to_json("stacked_assets") as "stack"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
left join "asset_stack" on "asset_stack"."id" = "assets"."stackId"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join "stack" on "stack"."id" = "asset"."stackId"
left join lateral (
select
"asset_stack".*,
"stack".*,
count("stacked") as "assetCount"
from
"assets" as "stacked"
"asset" as "stacked"
where
"stacked"."stackId" = "asset_stack"."id"
"stacked"."stackId" = "stack"."id"
group by
"asset_stack"."id"
) as "stacked_assets" on "asset_stack"."id" is not null
"stack"."id"
) as "stacked_assets" on "stack"."id" is not null
where
"assets"."ownerId" = $1::uuid
and "assets"."visibility" != $2
and "assets"."updatedAt" <= $3
and "assets"."id" > $4
"asset"."ownerId" = $1::uuid
and "asset"."visibility" != $2
and "asset"."updatedAt" <= $3
and "asset"."id" > $4
order by
"assets"."id"
"asset"."id"
limit
$5
-- AssetRepository.getChangedDeltaSync
select
"assets".*,
to_json("exif") as "exifInfo",
"asset".*,
to_json("asset_exif") as "exifInfo",
to_json("stacked_assets") as "stack"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
left join "asset_stack" on "asset_stack"."id" = "assets"."stackId"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
left join "stack" on "stack"."id" = "asset"."stackId"
left join lateral (
select
"asset_stack".*,
"stack".*,
count("stacked") as "assetCount"
from
"assets" as "stacked"
"asset" as "stacked"
where
"stacked"."stackId" = "asset_stack"."id"
"stacked"."stackId" = "stack"."id"
group by
"asset_stack"."id"
) as "stacked_assets" on "asset_stack"."id" is not null
"stack"."id"
) as "stacked_assets" on "stack"."id" is not null
where
"assets"."ownerId" = any ($1::uuid[])
and "assets"."visibility" != $2
and "assets"."updatedAt" > $3
"asset"."ownerId" = any ($1::uuid[])
and "asset"."visibility" != $2
and "asset"."updatedAt" > $3
limit
$4
-- AssetRepository.detectOfflineExternalAssets
update "assets"
update "asset"
set
"isOffline" = $1,
"deletedAt" = $2
@ -449,9 +449,9 @@ where
select
"originalPath"
from
"assets"
"asset"
where
"assets"."originalPath" = "path"
"asset"."originalPath" = "path"
and "libraryId" = $2::uuid
and "isExternal" = $3
)

View File

@ -4,31 +4,31 @@
with
"duplicates" as (
select
"assets"."duplicateId",
"asset"."duplicateId",
json_agg(
"asset"
"asset2"
order by
"assets"."localDateTime" asc
"asset"."localDateTime" asc
) as "assets"
from
"assets"
"asset"
left join lateral (
select
"assets".*,
"exif" as "exifInfo"
"asset".*,
"asset_exif" as "exifInfo"
from
"exif"
"asset_exif"
where
"exif"."assetId" = "assets"."id"
) as "asset" on true
"asset_exif"."assetId" = "asset"."id"
) as "asset2" on true
where
"assets"."visibility" in ('archive', 'timeline')
and "assets"."ownerId" = $1::uuid
and "assets"."duplicateId" is not null
and "assets"."deletedAt" is null
and "assets"."stackId" is null
"asset"."visibility" in ('archive', 'timeline')
and "asset"."ownerId" = $1::uuid
and "asset"."duplicateId" is not null
and "asset"."deletedAt" is null
and "asset"."stackId" is null
group by
"assets"."duplicateId"
"asset"."duplicateId"
),
"unique" as (
select
@ -39,13 +39,13 @@ with
json_array_length("assets") = $2
),
"removed_unique" as (
update "assets"
update "asset"
set
"duplicateId" = $3
from
"unique"
where
"assets"."duplicateId" = "unique"."duplicateId"
"asset"."duplicateId" = "unique"."duplicateId"
)
select
*
@ -61,7 +61,7 @@ where
)
-- DuplicateRepository.delete
update "assets"
update "asset"
set
"duplicateId" = $1
where
@ -69,7 +69,7 @@ where
and "duplicateId" = $3
-- DuplicateRepository.deleteAll
update "assets"
update "asset"
set
"duplicateId" = $1
where
@ -83,19 +83,19 @@ set
with
"cte" as (
select
"assets"."id" as "assetId",
"assets"."duplicateId",
"asset"."id" as "assetId",
"asset"."duplicateId",
smart_search.embedding <=> $1 as "distance"
from
"assets"
inner join "smart_search" on "assets"."id" = "smart_search"."assetId"
"asset"
inner join "smart_search" on "asset"."id" = "smart_search"."assetId"
where
"assets"."visibility" in ('archive', 'timeline')
and "assets"."ownerId" = any ($2::uuid[])
and "assets"."deletedAt" is null
and "assets"."type" = $3
and "assets"."id" != $4::uuid
and "assets"."stackId" is null
"asset"."visibility" in ('archive', 'timeline')
and "asset"."ownerId" = any ($2::uuid[])
and "asset"."deletedAt" is null
and "asset"."type" = $3
and "asset"."id" != $4::uuid
and "asset"."stackId" is null
order by
"distance"
limit
@ -110,7 +110,7 @@ where
commit
-- DuplicateRepository.merge
update "assets"
update "asset"
set
where
(

View File

@ -2,30 +2,30 @@
-- LibraryRepository.get
select
"libraries".*
"library".*
from
"libraries"
"library"
where
"libraries"."id" = $1
and "libraries"."deletedAt" is null
"library"."id" = $1
and "library"."deletedAt" is null
-- LibraryRepository.getAll
select
"libraries".*
"library".*
from
"libraries"
"library"
where
"libraries"."deletedAt" is null
"library"."deletedAt" is null
order by
"createdAt" asc
-- LibraryRepository.getAllDeleted
select
"libraries".*
"library".*
from
"libraries"
"library"
where
"libraries"."deletedAt" is not null
"library"."deletedAt" is not null
order by
"createdAt" asc
@ -34,32 +34,32 @@ select
count(*) filter (
where
(
"assets"."type" = $1
and "assets"."visibility" != $2
"asset"."type" = $1
and "asset"."visibility" != $2
)
) as "photos",
count(*) filter (
where
(
"assets"."type" = $3
and "assets"."visibility" != $4
"asset"."type" = $3
and "asset"."visibility" != $4
)
) as "videos",
coalesce(sum("exif"."fileSizeInByte"), $5) as "usage"
coalesce(sum("asset_exif"."fileSizeInByte"), $5) as "usage"
from
"libraries"
inner join "assets" on "assets"."libraryId" = "libraries"."id"
left join "exif" on "exif"."assetId" = "assets"."id"
"library"
inner join "asset" on "asset"."libraryId" = "library"."id"
left join "asset_exif" on "asset_exif"."assetId" = "asset"."id"
where
"libraries"."id" = $6
"library"."id" = $6
group by
"libraries"."id"
"library"."id"
select
0::int as "photos",
0::int as "videos",
0::int as "usage",
0::int as "total"
from
"libraries"
"library"
where
"libraries"."id" = $1
"library"."id" = $1

View File

@ -3,28 +3,28 @@
-- MapRepository.getMapMarkers
select
"id",
"exif"."latitude" as "lat",
"exif"."longitude" as "lon",
"exif"."city",
"exif"."state",
"exif"."country"
"asset_exif"."latitude" as "lat",
"asset_exif"."longitude" as "lon",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
and "exif"."latitude" is not null
and "exif"."longitude" is not null
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
and "asset_exif"."latitude" is not null
and "asset_exif"."longitude" is not null
where
"assets"."visibility" = $1
"asset"."visibility" = $1
and "deletedAt" is null
and (
"ownerId" in ($2)
or exists (
select
from
"albums_assets_assets"
"album_asset"
where
"assets"."id" = "albums_assets_assets"."assetsId"
and "albums_assets_assets"."albumsId" in ($3)
"asset"."id" = "album_asset"."assetsId"
and "album_asset"."albumsId" in ($3)
)
)
order by

View File

@ -4,7 +4,7 @@
select
count(*) as "total"
from
"memories"
"memory"
where
"deletedAt" is null
and "ownerId" = $1
@ -13,7 +13,7 @@ where
select
count(*) as "total"
from
"memories"
"memory"
where
(
"showAt" is null
@ -34,21 +34,21 @@ select
from
(
select
"assets".*
"asset".*
from
"assets"
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
"asset"
inner join "memory_asset" on "asset"."id" = "memory_asset"."assetsId"
where
"memories_assets_assets"."memoriesId" = "memories"."id"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"memory_asset"."memoriesId" = "memory"."id"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as agg
) as "assets",
"memories".*
"memory".*
from
"memories"
"memory"
where
"deletedAt" is null
and "ownerId" = $1
@ -63,21 +63,21 @@ select
from
(
select
"assets".*
"asset".*
from
"assets"
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
"asset"
inner join "memory_asset" on "asset"."id" = "memory_asset"."assetsId"
where
"memories_assets_assets"."memoriesId" = "memories"."id"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"memory_asset"."memoriesId" = "memory"."id"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as agg
) as "assets",
"memories".*
"memory".*
from
"memories"
"memory"
where
(
"showAt" is null
@ -94,66 +94,66 @@ order by
-- MemoryRepository.get
select
"memories".*,
"memory".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"assets".*
"asset".*
from
"assets"
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
"asset"
inner join "memory_asset" on "asset"."id" = "memory_asset"."assetsId"
where
"memories_assets_assets"."memoriesId" = "memories"."id"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"memory_asset"."memoriesId" = "memory"."id"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as agg
) as "assets"
from
"memories"
"memory"
where
"id" = $1
and "deletedAt" is null
-- MemoryRepository.update
update "memories"
update "memory"
set
"ownerId" = $1,
"isSaved" = $2
where
"id" = $3
select
"memories".*,
"memory".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"assets".*
"asset".*
from
"assets"
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
"asset"
inner join "memory_asset" on "asset"."id" = "memory_asset"."assetsId"
where
"memories_assets_assets"."memoriesId" = "memories"."id"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"memory_asset"."memoriesId" = "memory"."id"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as agg
) as "assets"
from
"memories"
"memory"
where
"id" = $1
and "deletedAt" is null
-- MemoryRepository.delete
delete from "memories"
delete from "memory"
where
"id" = $1
@ -161,13 +161,13 @@ where
select
"assetsId"
from
"memories_assets_assets"
"memory_asset"
where
"memoriesId" = $1
and "assetsId" in ($2)
-- MemoryRepository.addAssetIds
insert into
"memories_assets_assets" ("memoriesId", "assetsId")
"memory_asset" ("memoriesId", "assetsId")
values
($1, $2)

View File

@ -11,7 +11,7 @@ select
"data",
"readAt"
from
"notifications"
"notification"
where
"userId" = $1
and "deletedAt" is null
@ -29,7 +29,7 @@ select
"data",
"readAt"
from
"notifications"
"notification"
where
(
"userId" = $1

View File

@ -2,7 +2,7 @@
-- PartnerRepository.getAll
select
"partners".*,
"partner".*,
(
select
to_json(obj)
@ -16,9 +16,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedBy"
"user" as "sharedBy"
where
"sharedBy"."id" = "partners"."sharedById"
"sharedBy"."id" = "partner"."sharedById"
) as obj
) as "sharedBy",
(
@ -34,16 +34,16 @@ select
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedWith"
"user" as "sharedWith"
where
"sharedWith"."id" = "partners"."sharedWithId"
"sharedWith"."id" = "partner"."sharedWithId"
) as obj
) as "sharedWith"
from
"partners"
inner join "users" as "sharedBy" on "partners"."sharedById" = "sharedBy"."id"
"partner"
inner join "user" as "sharedBy" on "partner"."sharedById" = "sharedBy"."id"
and "sharedBy"."deletedAt" is null
inner join "users" as "sharedWith" on "partners"."sharedWithId" = "sharedWith"."id"
inner join "user" as "sharedWith" on "partner"."sharedWithId" = "sharedWith"."id"
and "sharedWith"."deletedAt" is null
where
(
@ -53,7 +53,7 @@ where
-- PartnerRepository.get
select
"partners".*,
"partner".*,
(
select
to_json(obj)
@ -67,9 +67,9 @@ select
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedBy"
"user" as "sharedBy"
where
"sharedBy"."id" = "partners"."sharedById"
"sharedBy"."id" = "partner"."sharedById"
) as obj
) as "sharedBy",
(
@ -85,23 +85,23 @@ select
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedWith"
"user" as "sharedWith"
where
"sharedWith"."id" = "partners"."sharedWithId"
"sharedWith"."id" = "partner"."sharedWithId"
) as obj
) as "sharedWith"
from
"partners"
inner join "users" as "sharedBy" on "partners"."sharedById" = "sharedBy"."id"
"partner"
inner join "user" as "sharedBy" on "partner"."sharedById" = "sharedBy"."id"
and "sharedBy"."deletedAt" is null
inner join "users" as "sharedWith" on "partners"."sharedWithId" = "sharedWith"."id"
inner join "user" as "sharedWith" on "partner"."sharedWithId" = "sharedWith"."id"
and "sharedWith"."deletedAt" is null
where
"sharedWithId" = $1
and "sharedById" = $2
-- PartnerRepository.update
update "partners"
update "partner"
set
"inTimeline" = $1
where
@ -122,9 +122,9 @@ returning
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedBy"
"user" as "sharedBy"
where
"sharedBy"."id" = "partners"."sharedById"
"sharedBy"."id" = "partner"."sharedById"
) as obj
) as "sharedBy",
(
@ -140,14 +140,14 @@ returning
"profileImagePath",
"profileChangedAt"
from
"users" as "sharedWith"
"user" as "sharedWith"
where
"sharedWith"."id" = "partners"."sharedWithId"
"sharedWith"."id" = "partner"."sharedWithId"
) as obj
) as "sharedWith"
-- PartnerRepository.remove
delete from "partners"
delete from "partner"
where
"sharedWithId" = $1
and "sharedById" = $2

View File

@ -1,11 +1,11 @@
-- NOTE: This file is auto generated by ./sql-generator
-- PersonRepository.reassignFaces
update "asset_faces"
update "asset_face"
set
"personId" = $1
where
"asset_faces"."personId" = $2
"asset_face"."personId" = $2
-- PersonRepository.delete
delete from "person"
@ -17,26 +17,26 @@ select
"person".*
from
"person"
inner join "asset_faces" on "asset_faces"."personId" = "person"."id"
inner join "assets" on "asset_faces"."assetId" = "assets"."id"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
inner join "asset_face" on "asset_face"."personId" = "person"."id"
inner join "asset" on "asset_face"."assetId" = "asset"."id"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
where
"person"."ownerId" = $1
and "asset_faces"."deletedAt" is null
and "asset_face"."deletedAt" is null
and "person"."isHidden" = $2
group by
"person"."id"
having
(
"person"."name" != $3
or count("asset_faces"."assetId") >= $4
or count("asset_face"."assetId") >= $4
)
order by
"person"."isHidden" asc,
"person"."isFavorite" desc,
NULLIF(person.name, '') is null asc,
count("asset_faces"."assetId") desc,
count("asset_face"."assetId") desc,
NULLIF(person.name, '') asc nulls last,
"person"."createdAt"
limit
@ -49,17 +49,17 @@ select
"person".*
from
"person"
left join "asset_faces" on "asset_faces"."personId" = "person"."id"
left join "asset_face" on "asset_face"."personId" = "person"."id"
where
"asset_faces"."deletedAt" is null
"asset_face"."deletedAt" is null
group by
"person"."id"
having
count("asset_faces"."assetId") = $1
count("asset_face"."assetId") = $1
-- PersonRepository.getFaces
select
"asset_faces".*,
"asset_face".*,
(
select
to_json(obj)
@ -70,20 +70,20 @@ select
from
"person"
where
"person"."id" = "asset_faces"."personId"
"person"."id" = "asset_face"."personId"
) as obj
) as "person"
from
"asset_faces"
"asset_face"
where
"asset_faces"."assetId" = $1
and "asset_faces"."deletedAt" is null
"asset_face"."assetId" = $1
and "asset_face"."deletedAt" is null
order by
"asset_faces"."boundingBoxX1" asc
"asset_face"."boundingBoxX1" asc
-- PersonRepository.getFaceById
select
"asset_faces".*,
"asset_face".*,
(
select
to_json(obj)
@ -94,33 +94,33 @@ select
from
"person"
where
"person"."id" = "asset_faces"."personId"
"person"."id" = "asset_face"."personId"
) as obj
) as "person"
from
"asset_faces"
"asset_face"
where
"asset_faces"."id" = $1
and "asset_faces"."deletedAt" is null
"asset_face"."id" = $1
and "asset_face"."deletedAt" is null
-- PersonRepository.getFaceForFacialRecognitionJob
select
"asset_faces"."id",
"asset_faces"."personId",
"asset_faces"."sourceType",
"asset_face"."id",
"asset_face"."personId",
"asset_face"."sourceType",
(
select
to_json(obj)
from
(
select
"assets"."ownerId",
"assets"."visibility",
"assets"."fileCreatedAt"
"asset"."ownerId",
"asset"."visibility",
"asset"."fileCreatedAt"
from
"assets"
"asset"
where
"assets"."id" = "asset_faces"."assetId"
"asset"."id" = "asset_face"."assetId"
) as obj
) as "asset",
(
@ -133,51 +133,51 @@ select
from
"face_search"
where
"face_search"."faceId" = "asset_faces"."id"
"face_search"."faceId" = "asset_face"."id"
) as obj
) as "faceSearch"
from
"asset_faces"
"asset_face"
where
"asset_faces"."id" = $1
and "asset_faces"."deletedAt" is null
"asset_face"."id" = $1
and "asset_face"."deletedAt" is null
-- PersonRepository.getDataForThumbnailGenerationJob
select
"person"."ownerId",
"asset_faces"."boundingBoxX1" as "x1",
"asset_faces"."boundingBoxY1" as "y1",
"asset_faces"."boundingBoxX2" as "x2",
"asset_faces"."boundingBoxY2" as "y2",
"asset_faces"."imageWidth" as "oldWidth",
"asset_faces"."imageHeight" as "oldHeight",
"assets"."type",
"assets"."originalPath",
"exif"."orientation" as "exifOrientation",
"asset_face"."boundingBoxX1" as "x1",
"asset_face"."boundingBoxY1" as "y1",
"asset_face"."boundingBoxX2" as "x2",
"asset_face"."boundingBoxY2" as "y2",
"asset_face"."imageWidth" as "oldWidth",
"asset_face"."imageHeight" as "oldHeight",
"asset"."type",
"asset"."originalPath",
"asset_exif"."orientation" as "exifOrientation",
(
select
"asset_files"."path"
"asset_file"."path"
from
"asset_files"
"asset_file"
where
"asset_files"."assetId" = "assets"."id"
and "asset_files"."type" = 'preview'
"asset_file"."assetId" = "asset"."id"
and "asset_file"."type" = 'preview'
) as "previewPath"
from
"person"
inner join "asset_faces" on "asset_faces"."id" = "person"."faceAssetId"
inner join "assets" on "asset_faces"."assetId" = "assets"."id"
left join "exif" on "exif"."assetId" = "assets"."id"
inner join "asset_face" on "asset_face"."id" = "person"."faceAssetId"
inner join "asset" on "asset_face"."assetId" = "asset"."id"
left join "asset_exif" on "asset_exif"."assetId" = "asset"."id"
where
"person"."id" = $1
and "asset_faces"."deletedAt" is null
and "asset_face"."deletedAt" is null
-- PersonRepository.reassignFace
update "asset_faces"
update "asset_face"
set
"personId" = $1
where
"asset_faces"."id" = $2
"asset_face"."id" = $2
-- PersonRepository.getByName
select
@ -209,15 +209,15 @@ where
-- PersonRepository.getStatistics
select
count(distinct ("assets"."id")) as "count"
count(distinct ("asset"."id")) as "count"
from
"asset_faces"
left join "assets" on "assets"."id" = "asset_faces"."assetId"
and "asset_faces"."personId" = $1
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"asset_face"
left join "asset" on "asset"."id" = "asset_face"."assetId"
and "asset_face"."personId" = $1
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
where
"asset_faces"."deletedAt" is null
"asset_face"."deletedAt" is null
-- PersonRepository.getNumberOfPeople
select
@ -235,18 +235,18 @@ where
exists (
select
from
"asset_faces"
"asset_face"
where
"asset_faces"."personId" = "person"."id"
and "asset_faces"."deletedAt" is null
"asset_face"."personId" = "person"."id"
and "asset_face"."deletedAt" is null
and exists (
select
from
"assets"
"asset"
where
"assets"."id" = "asset_faces"."assetId"
and "assets"."visibility" = 'timeline'
and "assets"."deletedAt" is null
"asset"."id" = "asset_face"."assetId"
and "asset"."visibility" = 'timeline'
and "asset"."deletedAt" is null
)
)
and "person"."ownerId" = $2
@ -268,18 +268,18 @@ from
-- PersonRepository.getFacesByIds
select
"asset_faces".*,
"asset_face".*,
(
select
to_json(obj)
from
(
select
"assets".*
"asset".*
from
"assets"
"asset"
where
"assets"."id" = "asset_faces"."assetId"
"asset"."id" = "asset_face"."assetId"
) as obj
) as "asset",
(
@ -292,24 +292,24 @@ select
from
"person"
where
"person"."id" = "asset_faces"."personId"
"person"."id" = "asset_face"."personId"
) as obj
) as "person"
from
"asset_faces"
"asset_face"
where
"asset_faces"."assetId" in ($1)
and "asset_faces"."personId" in ($2)
and "asset_faces"."deletedAt" is null
"asset_face"."assetId" in ($1)
and "asset_face"."personId" in ($2)
and "asset_face"."deletedAt" is null
-- PersonRepository.getRandomFace
select
"asset_faces".*
"asset_face".*
from
"asset_faces"
"asset_face"
where
"asset_faces"."personId" = $1
and "asset_faces"."deletedAt" is null
"asset_face"."personId" = $1
and "asset_face"."deletedAt" is null
-- PersonRepository.getLatestFaceDate
select
@ -318,16 +318,16 @@ from
"asset_job_status"
-- PersonRepository.deleteAssetFace
delete from "asset_faces"
delete from "asset_face"
where
"asset_faces"."id" = $1
"asset_face"."id" = $1
-- PersonRepository.softDeleteAssetFaces
update "asset_faces"
update "asset_face"
set
"deletedAt" = $1
where
"asset_faces"."id" = $2
"asset_face"."id" = $2
-- PersonRepository.getForPeopleDelete
select

View File

@ -2,19 +2,19 @@
-- SearchRepository.searchMetadata
select
"assets".*
"asset".*
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."visibility" = $1
and "assets"."fileCreatedAt" >= $2
and "exif"."lensModel" = $3
and "assets"."ownerId" = any ($4::uuid[])
and "assets"."isFavorite" = $5
and "assets"."deletedAt" is null
"asset"."visibility" = $1
and "asset"."fileCreatedAt" >= $2
and "asset_exif"."lensModel" = $3
and "asset"."ownerId" = any ($4::uuid[])
and "asset"."isFavorite" = $5
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" desc
"asset"."fileCreatedAt" desc
limit
$6
offset
@ -24,31 +24,31 @@ offset
select
count(*) as "total"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."visibility" = $1
and "assets"."fileCreatedAt" >= $2
and "exif"."lensModel" = $3
and "assets"."ownerId" = any ($4::uuid[])
and "assets"."isFavorite" = $5
and "assets"."deletedAt" is null
"asset"."visibility" = $1
and "asset"."fileCreatedAt" >= $2
and "asset_exif"."lensModel" = $3
and "asset"."ownerId" = any ($4::uuid[])
and "asset"."isFavorite" = $5
and "asset"."deletedAt" is null
-- SearchRepository.searchRandom
(
select
"assets".*
"asset".*
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."visibility" = $1
and "assets"."fileCreatedAt" >= $2
and "exif"."lensModel" = $3
and "assets"."ownerId" = any ($4::uuid[])
and "assets"."isFavorite" = $5
and "assets"."deletedAt" is null
and "assets"."id" < $6
"asset"."visibility" = $1
and "asset"."fileCreatedAt" >= $2
and "asset_exif"."lensModel" = $3
and "asset"."ownerId" = any ($4::uuid[])
and "asset"."isFavorite" = $5
and "asset"."deletedAt" is null
and "asset"."id" < $6
order by
random()
limit
@ -57,18 +57,18 @@ where
union all
(
select
"assets".*
"asset".*
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."visibility" = $8
and "assets"."fileCreatedAt" >= $9
and "exif"."lensModel" = $10
and "assets"."ownerId" = any ($11::uuid[])
and "assets"."isFavorite" = $12
and "assets"."deletedAt" is null
and "assets"."id" > $13
"asset"."visibility" = $8
and "asset"."fileCreatedAt" >= $9
and "asset_exif"."lensModel" = $10
and "asset"."ownerId" = any ($11::uuid[])
and "asset"."isFavorite" = $12
and "asset"."deletedAt" is null
and "asset"."id" > $13
order by
random()
limit
@ -82,18 +82,18 @@ begin
set
local vchordrq.probes = 1
select
"assets".*
"asset".*
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
inner join "smart_search" on "assets"."id" = "smart_search"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
inner join "smart_search" on "asset"."id" = "smart_search"."assetId"
where
"assets"."visibility" = $1
and "assets"."fileCreatedAt" >= $2
and "exif"."lensModel" = $3
and "assets"."ownerId" = any ($4::uuid[])
and "assets"."isFavorite" = $5
and "assets"."deletedAt" is null
"asset"."visibility" = $1
and "asset"."fileCreatedAt" >= $2
and "asset_exif"."lensModel" = $3
and "asset"."ownerId" = any ($4::uuid[])
and "asset"."isFavorite" = $5
and "asset"."deletedAt" is null
order by
smart_search.embedding <=> $6
limit
@ -109,17 +109,17 @@ set
with
"cte" as (
select
"asset_faces"."id",
"asset_faces"."personId",
"asset_face"."id",
"asset_face"."personId",
face_search.embedding <=> $1 as "distance"
from
"asset_faces"
inner join "assets" on "assets"."id" = "asset_faces"."assetId"
inner join "face_search" on "face_search"."faceId" = "asset_faces"."id"
left join "person" on "person"."id" = "asset_faces"."personId"
"asset_face"
inner join "asset" on "asset"."id" = "asset_face"."assetId"
inner join "face_search" on "face_search"."faceId" = "asset_face"."id"
left join "person" on "person"."id" = "asset_face"."personId"
where
"assets"."ownerId" = any ($2::uuid[])
and "assets"."deletedAt" is null
"asset"."ownerId" = any ($2::uuid[])
and "asset"."deletedAt" is null
order by
"distance"
limit
@ -165,13 +165,13 @@ with recursive
"city",
"assetId"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."ownerId" = any ($1::uuid[])
and "assets"."visibility" = $2
and "assets"."type" = $3
and "assets"."deletedAt" is null
"asset"."ownerId" = any ($1::uuid[])
and "asset"."visibility" = $2
and "asset"."type" = $3
and "asset"."deletedAt" is null
order by
"city"
limit
@ -189,14 +189,14 @@ with recursive
"city",
"assetId"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."ownerId" = any ($5::uuid[])
and "assets"."visibility" = $6
and "assets"."type" = $7
and "assets"."deletedAt" is null
and "exif"."city" > "cte"."city"
"asset"."ownerId" = any ($5::uuid[])
and "asset"."visibility" = $6
and "asset"."type" = $7
and "asset"."deletedAt" is null
and "asset_exif"."city" > "cte"."city"
order by
"city"
limit
@ -205,21 +205,21 @@ with recursive
)
)
select
"assets".*,
to_jsonb("exif") as "exifInfo"
"asset".*,
to_jsonb("asset_exif") as "exifInfo"
from
"assets"
inner join "exif" on "assets"."id" = "exif"."assetId"
inner join "cte" on "assets"."id" = "cte"."assetId"
"asset"
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
inner join "cte" on "asset"."id" = "cte"."assetId"
order by
"exif"."city"
"asset_exif"."city"
-- SearchRepository.getStates
select distinct
on ("state") "state"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"ownerId" = any ($1::uuid[])
and "visibility" = $2
@ -230,8 +230,8 @@ where
select distinct
on ("city") "city"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"ownerId" = any ($1::uuid[])
and "visibility" = $2
@ -242,8 +242,8 @@ where
select distinct
on ("make") "make"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"ownerId" = any ($1::uuid[])
and "visibility" = $2
@ -254,8 +254,8 @@ where
select distinct
on ("model") "model"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"ownerId" = any ($1::uuid[])
and "visibility" = $2

View File

@ -6,68 +6,68 @@ select
"expiresAt",
"pinExpiresAt"
from
"sessions"
"session"
where
"id" = $1
-- SessionRepository.getByToken
select
"sessions"."id",
"sessions"."isPendingSyncReset",
"sessions"."updatedAt",
"sessions"."pinExpiresAt",
"session"."id",
"session"."isPendingSyncReset",
"session"."updatedAt",
"session"."pinExpiresAt",
(
select
to_json(obj)
from
(
select
"users"."id",
"users"."name",
"users"."email",
"users"."isAdmin",
"users"."quotaUsageInBytes",
"users"."quotaSizeInBytes"
"user"."id",
"user"."name",
"user"."email",
"user"."isAdmin",
"user"."quotaUsageInBytes",
"user"."quotaSizeInBytes"
from
"users"
"user"
where
"users"."id" = "sessions"."userId"
and "users"."deletedAt" is null
"user"."id" = "session"."userId"
and "user"."deletedAt" is null
) as obj
) as "user"
from
"sessions"
"session"
where
"sessions"."token" = $1
"session"."token" = $1
and (
"sessions"."expiresAt" is null
or "sessions"."expiresAt" > $2
"session"."expiresAt" is null
or "session"."expiresAt" > $2
)
-- SessionRepository.getByUserId
select
"sessions".*
"session".*
from
"sessions"
inner join "users" on "users"."id" = "sessions"."userId"
and "users"."deletedAt" is null
"session"
inner join "user" on "user"."id" = "session"."userId"
and "user"."deletedAt" is null
where
"sessions"."userId" = $1
"session"."userId" = $1
and (
"sessions"."expiresAt" is null
or "sessions"."expiresAt" > $2
"session"."expiresAt" is null
or "session"."expiresAt" > $2
)
order by
"sessions"."updatedAt" desc,
"sessions"."createdAt" desc
"session"."updatedAt" desc,
"session"."createdAt" desc
-- SessionRepository.delete
delete from "sessions"
delete from "session"
where
"id" = $1::uuid
-- SessionRepository.lockAll
update "sessions"
update "session"
set
"pinExpiresAt" = $1
where
@ -75,12 +75,12 @@ where
-- SessionRepository.resetSyncProgress
begin
update "sessions"
update "session"
set
"isPendingSyncReset" = $1
where
"id" = $2
delete from "session_sync_checkpoints"
delete from "session_sync_checkpoint"
where
"sessionId" = $1
commit

View File

@ -2,7 +2,7 @@
-- SharedLinkRepository.get
select
"shared_links".*,
"shared_link".*,
coalesce(
json_agg("a") filter (
where
@ -12,31 +12,31 @@ select
) as "assets",
to_json("album") as "album"
from
"shared_links"
"shared_link"
left join lateral (
select
"assets".*,
"asset".*,
to_json("exifInfo") as "exifInfo"
from
"shared_link__asset"
inner join "assets" on "assets"."id" = "shared_link__asset"."assetsId"
"shared_link_asset"
inner join "asset" on "asset"."id" = "shared_link_asset"."assetsId"
inner join lateral (
select
"exif".*
"asset_exif".*
from
"exif"
"asset_exif"
where
"exif"."assetId" = "assets"."id"
"asset_exif"."assetId" = "asset"."id"
) as "exifInfo" on true
where
"shared_links"."id" = "shared_link__asset"."sharedLinksId"
and "assets"."deletedAt" is null
"shared_link"."id" = "shared_link_asset"."sharedLinksId"
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as "a" on true
left join lateral (
select
"albums".*,
"album".*,
coalesce(
json_agg("assets") filter (
where
@ -46,151 +46,151 @@ from
) as "assets",
to_json("owner") as "owner"
from
"albums"
left join "albums_assets_assets" on "albums_assets_assets"."albumsId" = "albums"."id"
"album"
left join "album_asset" on "album_asset"."albumsId" = "album"."id"
left join lateral (
select
"assets".*,
to_json("assets_exifInfo") as "exifInfo"
"asset".*,
to_json("exifInfo") as "exifInfo"
from
"assets"
"asset"
inner join lateral (
select
"exif".*
"asset_exif".*
from
"exif"
"asset_exif"
where
"exif"."assetId" = "assets"."id"
) as "assets_exifInfo" on true
"asset_exif"."assetId" = "asset"."id"
) as "exifInfo" on true
where
"albums_assets_assets"."assetsId" = "assets"."id"
and "assets"."deletedAt" is null
"album_asset"."assetsId" = "asset"."id"
and "asset"."deletedAt" is null
order by
"assets"."fileCreatedAt" asc
"asset"."fileCreatedAt" asc
) as "assets" on true
inner join lateral (
select
"users".*
"user".*
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
and "users"."deletedAt" is null
"user"."id" = "album"."ownerId"
and "user"."deletedAt" is null
) as "owner" on true
where
"albums"."id" = "shared_links"."albumId"
and "albums"."deletedAt" is null
"album"."id" = "shared_link"."albumId"
and "album"."deletedAt" is null
group by
"albums"."id",
"album"."id",
"owner".*
) as "album" on true
where
"shared_links"."id" = $1
and "shared_links"."userId" = $2
"shared_link"."id" = $1
and "shared_link"."userId" = $2
and (
"shared_links"."type" = $3
"shared_link"."type" = $3
or "album"."id" is not null
)
group by
"shared_links"."id",
"shared_link"."id",
"album".*
order by
"shared_links"."createdAt" desc
"shared_link"."createdAt" desc
-- SharedLinkRepository.getAll
select distinct
on ("shared_links"."createdAt") "shared_links".*,
on ("shared_link"."createdAt") "shared_link".*,
"assets"."assets",
to_json("album") as "album"
from
"shared_links"
left join "shared_link__asset" on "shared_link__asset"."sharedLinksId" = "shared_links"."id"
"shared_link"
left join "shared_link_asset" on "shared_link_asset"."sharedLinksId" = "shared_link"."id"
left join lateral (
select
json_agg("assets") as "assets"
json_agg("asset") as "assets"
from
"assets"
"asset"
where
"assets"."id" = "shared_link__asset"."assetsId"
and "assets"."deletedAt" is null
"asset"."id" = "shared_link_asset"."assetsId"
and "asset"."deletedAt" is null
) as "assets" on true
left join lateral (
select
"albums".*,
"album".*,
to_json("owner") as "owner"
from
"albums"
"album"
inner join lateral (
select
"users"."id",
"users"."email",
"users"."createdAt",
"users"."profileImagePath",
"users"."isAdmin",
"users"."shouldChangePassword",
"users"."deletedAt",
"users"."oauthId",
"users"."updatedAt",
"users"."storageLabel",
"users"."name",
"users"."quotaSizeInBytes",
"users"."quotaUsageInBytes",
"users"."status",
"users"."profileChangedAt"
"user"."id",
"user"."email",
"user"."createdAt",
"user"."profileImagePath",
"user"."isAdmin",
"user"."shouldChangePassword",
"user"."deletedAt",
"user"."oauthId",
"user"."updatedAt",
"user"."storageLabel",
"user"."name",
"user"."quotaSizeInBytes",
"user"."quotaUsageInBytes",
"user"."status",
"user"."profileChangedAt"
from
"users"
"user"
where
"users"."id" = "albums"."ownerId"
and "users"."deletedAt" is null
"user"."id" = "album"."ownerId"
and "user"."deletedAt" is null
) as "owner" on true
where
"albums"."id" = "shared_links"."albumId"
and "albums"."deletedAt" is null
"album"."id" = "shared_link"."albumId"
and "album"."deletedAt" is null
) as "album" on true
where
"shared_links"."userId" = $1
"shared_link"."userId" = $1
and (
"shared_links"."type" = $2
"shared_link"."type" = $2
or "album"."id" is not null
)
and "shared_links"."albumId" = $3
and "shared_link"."albumId" = $3
order by
"shared_links"."createdAt" desc
"shared_link"."createdAt" desc
-- SharedLinkRepository.getByKey
select
"shared_links"."id",
"shared_links"."userId",
"shared_links"."expiresAt",
"shared_links"."showExif",
"shared_links"."allowUpload",
"shared_links"."allowDownload",
"shared_links"."password",
"shared_link"."id",
"shared_link"."userId",
"shared_link"."expiresAt",
"shared_link"."showExif",
"shared_link"."allowUpload",
"shared_link"."allowDownload",
"shared_link"."password",
(
select
to_json(obj)
from
(
select
"users"."id",
"users"."name",
"users"."email",
"users"."isAdmin",
"users"."quotaUsageInBytes",
"users"."quotaSizeInBytes"
"user"."id",
"user"."name",
"user"."email",
"user"."isAdmin",
"user"."quotaUsageInBytes",
"user"."quotaSizeInBytes"
from
"users"
"user"
where
"users"."id" = "shared_links"."userId"
"user"."id" = "shared_link"."userId"
) as obj
) as "user"
from
"shared_links"
left join "albums" on "albums"."id" = "shared_links"."albumId"
"shared_link"
left join "album" on "album"."id" = "shared_link"."albumId"
where
"shared_links"."key" = $1
and "albums"."deletedAt" is null
"shared_link"."key" = $1
and "album"."deletedAt" is null
and (
"shared_links"."type" = $2
or "albums"."id" is not null
"shared_link"."type" = $2
or "album"."id" is not null
)

View File

@ -2,66 +2,66 @@
-- StackRepository.search
select
"asset_stack".*,
"stack".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"assets".*,
"asset".*,
to_json("exifInfo") as "exifInfo"
from
"assets"
"asset"
inner join lateral (
select
"exif"."assetId",
"exif"."autoStackId",
"exif"."bitsPerSample",
"exif"."city",
"exif"."colorspace",
"exif"."country",
"exif"."dateTimeOriginal",
"exif"."description",
"exif"."exifImageHeight",
"exif"."exifImageWidth",
"exif"."exposureTime",
"exif"."fileSizeInByte",
"exif"."fNumber",
"exif"."focalLength",
"exif"."fps",
"exif"."iso",
"exif"."latitude",
"exif"."lensModel",
"exif"."livePhotoCID",
"exif"."longitude",
"exif"."make",
"exif"."model",
"exif"."modifyDate",
"exif"."orientation",
"exif"."profileDescription",
"exif"."projectionType",
"exif"."rating",
"exif"."state",
"exif"."timeZone"
"asset_exif"."assetId",
"asset_exif"."autoStackId",
"asset_exif"."bitsPerSample",
"asset_exif"."city",
"asset_exif"."colorspace",
"asset_exif"."country",
"asset_exif"."dateTimeOriginal",
"asset_exif"."description",
"asset_exif"."exifImageHeight",
"asset_exif"."exifImageWidth",
"asset_exif"."exposureTime",
"asset_exif"."fileSizeInByte",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."fps",
"asset_exif"."iso",
"asset_exif"."latitude",
"asset_exif"."lensModel",
"asset_exif"."livePhotoCID",
"asset_exif"."longitude",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."modifyDate",
"asset_exif"."orientation",
"asset_exif"."profileDescription",
"asset_exif"."projectionType",
"asset_exif"."rating",
"asset_exif"."state",
"asset_exif"."timeZone"
from
"exif"
"asset_exif"
where
"exif"."assetId" = "assets"."id"
"asset_exif"."assetId" = "asset"."id"
) as "exifInfo" on true
where
"assets"."deletedAt" is null
and "assets"."stackId" = "asset_stack"."id"
and "assets"."visibility" in ('archive', 'timeline')
"asset"."deletedAt" is null
and "asset"."stackId" = "stack"."id"
and "asset"."visibility" in ('archive', 'timeline')
) as agg
) as "assets"
from
"asset_stack"
"stack"
where
"asset_stack"."ownerId" = $1
"stack"."ownerId" = $1
-- StackRepository.delete
delete from "asset_stack"
delete from "stack"
where
"id" = $1::uuid
@ -74,72 +74,72 @@ select
from
(
select
"assets".*,
"asset".*,
(
select
coalesce(json_agg(agg), '[]')
from
(
select
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tags"
inner join "tag_asset" on "tags"."id" = "tag_asset"."tagsId"
"tag"
inner join "tag_asset" on "tag"."id" = "tag_asset"."tagsId"
where
"tag_asset"."assetsId" = "assets"."id"
"tag_asset"."assetsId" = "asset"."id"
) as agg
) as "tags",
to_json("exifInfo") as "exifInfo"
from
"assets"
"asset"
inner join lateral (
select
"exif"."assetId",
"exif"."autoStackId",
"exif"."bitsPerSample",
"exif"."city",
"exif"."colorspace",
"exif"."country",
"exif"."dateTimeOriginal",
"exif"."description",
"exif"."exifImageHeight",
"exif"."exifImageWidth",
"exif"."exposureTime",
"exif"."fileSizeInByte",
"exif"."fNumber",
"exif"."focalLength",
"exif"."fps",
"exif"."iso",
"exif"."latitude",
"exif"."lensModel",
"exif"."livePhotoCID",
"exif"."longitude",
"exif"."make",
"exif"."model",
"exif"."modifyDate",
"exif"."orientation",
"exif"."profileDescription",
"exif"."projectionType",
"exif"."rating",
"exif"."state",
"exif"."timeZone"
"asset_exif"."assetId",
"asset_exif"."autoStackId",
"asset_exif"."bitsPerSample",
"asset_exif"."city",
"asset_exif"."colorspace",
"asset_exif"."country",
"asset_exif"."dateTimeOriginal",
"asset_exif"."description",
"asset_exif"."exifImageHeight",
"asset_exif"."exifImageWidth",
"asset_exif"."exposureTime",
"asset_exif"."fileSizeInByte",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."fps",
"asset_exif"."iso",
"asset_exif"."latitude",
"asset_exif"."lensModel",
"asset_exif"."livePhotoCID",
"asset_exif"."longitude",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."modifyDate",
"asset_exif"."orientation",
"asset_exif"."profileDescription",
"asset_exif"."projectionType",
"asset_exif"."rating",
"asset_exif"."state",
"asset_exif"."timeZone"
from
"exif"
"asset_exif"
where
"exif"."assetId" = "assets"."id"
"asset_exif"."assetId" = "asset"."id"
) as "exifInfo" on true
where
"assets"."deletedAt" is null
and "assets"."stackId" = "asset_stack"."id"
and "assets"."visibility" in ('archive', 'timeline')
"asset"."deletedAt" is null
and "asset"."stackId" = "stack"."id"
and "asset"."visibility" in ('archive', 'timeline')
) as agg
) as "assets"
from
"asset_stack"
"stack"
where
"id" = $1::uuid

View File

@ -5,11 +5,11 @@ select
"type",
"ack"
from
"session_sync_checkpoints"
"session_sync_checkpoint"
where
"sessionId" = $1
-- SyncCheckpointRepository.deleteAll
delete from "session_sync_checkpoints"
delete from "session_sync_checkpoint"
where
"sessionId" = $1

View File

@ -5,7 +5,7 @@ select
"albumsId" as "id",
"createId"
from
"albums_shared_users_users"
"album_user"
where
"usersId" = $1
and "createId" >= $2
@ -18,7 +18,7 @@ select
"id",
"albumId"
from
"albums_audit"
"album_audit"
where
"userId" = $1
and "deletedAt" < now() - interval '1 millisecond'
@ -27,165 +27,165 @@ order by
-- SyncRepository.album.getUpserts
select distinct
on ("albums"."id", "albums"."updateId") "albums"."id",
"albums"."ownerId",
"albums"."albumName" as "name",
"albums"."description",
"albums"."createdAt",
"albums"."updatedAt",
"albums"."albumThumbnailAssetId" as "thumbnailAssetId",
"albums"."isActivityEnabled",
"albums"."order",
"albums"."updateId"
on ("album"."id", "album"."updateId") "album"."id",
"album"."ownerId",
"album"."albumName" as "name",
"album"."description",
"album"."createdAt",
"album"."updatedAt",
"album"."albumThumbnailAssetId" as "thumbnailAssetId",
"album"."isActivityEnabled",
"album"."order",
"album"."updateId"
from
"albums"
left join "albums_shared_users_users" as "album_users" on "albums"."id" = "album_users"."albumsId"
"album"
left join "album_user" as "album_users" on "album"."id" = "album_users"."albumsId"
where
"albums"."updatedAt" < now() - interval '1 millisecond'
"album"."updatedAt" < now() - interval '1 millisecond'
and (
"albums"."ownerId" = $1
"album"."ownerId" = $1
or "album_users"."usersId" = $2
)
order by
"albums"."updateId" asc
"album"."updateId" asc
-- SyncRepository.albumAsset.getBackfill
select
"assets"."id",
"assets"."ownerId",
"assets"."originalFileName",
"assets"."thumbhash",
"assets"."checksum",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."localDateTime",
"assets"."type",
"assets"."deletedAt",
"assets"."isFavorite",
"assets"."visibility",
"assets"."duration",
"assets"."updateId"
"asset"."id",
"asset"."ownerId",
"asset"."originalFileName",
"asset"."thumbhash",
"asset"."checksum",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."localDateTime",
"asset"."type",
"asset"."deletedAt",
"asset"."isFavorite",
"asset"."visibility",
"asset"."duration",
"asset"."updateId"
from
"assets"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."assetsId" = "assets"."id"
"asset"
inner join "album_asset" on "album_asset"."assetsId" = "asset"."id"
where
"album_assets"."albumsId" = $1
and "assets"."updatedAt" < now() - interval '1 millisecond'
and "assets"."updateId" <= $2
and "assets"."updateId" >= $3
"album_asset"."albumsId" = $1
and "asset"."updatedAt" < now() - interval '1 millisecond'
and "asset"."updateId" <= $2
and "asset"."updateId" >= $3
order by
"assets"."updateId" asc
"asset"."updateId" asc
-- SyncRepository.albumAsset.getUpserts
select
"assets"."id",
"assets"."ownerId",
"assets"."originalFileName",
"assets"."thumbhash",
"assets"."checksum",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."localDateTime",
"assets"."type",
"assets"."deletedAt",
"assets"."isFavorite",
"assets"."visibility",
"assets"."duration",
"assets"."updateId"
"asset"."id",
"asset"."ownerId",
"asset"."originalFileName",
"asset"."thumbhash",
"asset"."checksum",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."localDateTime",
"asset"."type",
"asset"."deletedAt",
"asset"."isFavorite",
"asset"."visibility",
"asset"."duration",
"asset"."updateId"
from
"assets"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."assetsId" = "assets"."id"
inner join "albums" on "albums"."id" = "album_assets"."albumsId"
left join "albums_shared_users_users" as "album_users" on "album_users"."albumsId" = "album_assets"."albumsId"
"asset"
inner join "album_asset" on "album_asset"."assetsId" = "asset"."id"
inner join "album" on "album"."id" = "album_asset"."albumsId"
left join "album_user" on "album_user"."albumsId" = "album_asset"."albumsId"
where
"assets"."updatedAt" < now() - interval '1 millisecond'
"asset"."updatedAt" < now() - interval '1 millisecond'
and (
"albums"."ownerId" = $1
or "album_users"."usersId" = $2
"album"."ownerId" = $1
or "album_user"."usersId" = $2
)
order by
"assets"."updateId" asc
"asset"."updateId" asc
-- SyncRepository.albumAssetExif.getBackfill
select
"exif"."assetId",
"exif"."description",
"exif"."exifImageWidth",
"exif"."exifImageHeight",
"exif"."fileSizeInByte",
"exif"."orientation",
"exif"."dateTimeOriginal",
"exif"."modifyDate",
"exif"."timeZone",
"exif"."latitude",
"exif"."longitude",
"exif"."projectionType",
"exif"."city",
"exif"."state",
"exif"."country",
"exif"."make",
"exif"."model",
"exif"."lensModel",
"exif"."fNumber",
"exif"."focalLength",
"exif"."iso",
"exif"."exposureTime",
"exif"."profileDescription",
"exif"."rating",
"exif"."fps",
"exif"."updateId"
"asset_exif"."assetId",
"asset_exif"."description",
"asset_exif"."exifImageWidth",
"asset_exif"."exifImageHeight",
"asset_exif"."fileSizeInByte",
"asset_exif"."orientation",
"asset_exif"."dateTimeOriginal",
"asset_exif"."modifyDate",
"asset_exif"."timeZone",
"asset_exif"."latitude",
"asset_exif"."longitude",
"asset_exif"."projectionType",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."lensModel",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."iso",
"asset_exif"."exposureTime",
"asset_exif"."profileDescription",
"asset_exif"."rating",
"asset_exif"."fps",
"asset_exif"."updateId"
from
"exif"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."assetsId" = "exif"."assetId"
"asset_exif"
inner join "album_asset" on "album_asset"."assetsId" = "asset_exif"."assetId"
where
"album_assets"."albumsId" = $1
and "exif"."updatedAt" < now() - interval '1 millisecond'
and "exif"."updateId" <= $2
and "exif"."updateId" >= $3
"album_asset"."albumsId" = $1
and "asset_exif"."updatedAt" < now() - interval '1 millisecond'
and "asset_exif"."updateId" <= $2
and "asset_exif"."updateId" >= $3
order by
"exif"."updateId" asc
"asset_exif"."updateId" asc
-- SyncRepository.albumAssetExif.getUpserts
select
"exif"."assetId",
"exif"."description",
"exif"."exifImageWidth",
"exif"."exifImageHeight",
"exif"."fileSizeInByte",
"exif"."orientation",
"exif"."dateTimeOriginal",
"exif"."modifyDate",
"exif"."timeZone",
"exif"."latitude",
"exif"."longitude",
"exif"."projectionType",
"exif"."city",
"exif"."state",
"exif"."country",
"exif"."make",
"exif"."model",
"exif"."lensModel",
"exif"."fNumber",
"exif"."focalLength",
"exif"."iso",
"exif"."exposureTime",
"exif"."profileDescription",
"exif"."rating",
"exif"."fps",
"exif"."updateId"
"asset_exif"."assetId",
"asset_exif"."description",
"asset_exif"."exifImageWidth",
"asset_exif"."exifImageHeight",
"asset_exif"."fileSizeInByte",
"asset_exif"."orientation",
"asset_exif"."dateTimeOriginal",
"asset_exif"."modifyDate",
"asset_exif"."timeZone",
"asset_exif"."latitude",
"asset_exif"."longitude",
"asset_exif"."projectionType",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."lensModel",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."iso",
"asset_exif"."exposureTime",
"asset_exif"."profileDescription",
"asset_exif"."rating",
"asset_exif"."fps",
"asset_exif"."updateId"
from
"exif"
inner join "albums_assets_assets" as "album_assets" on "album_assets"."assetsId" = "exif"."assetId"
inner join "albums" on "albums"."id" = "album_assets"."albumsId"
left join "albums_shared_users_users" as "album_users" on "album_users"."albumsId" = "album_assets"."albumsId"
"asset_exif"
inner join "album_asset" on "album_asset"."assetsId" = "asset_exif"."assetId"
inner join "album" on "album"."id" = "album_asset"."albumsId"
left join "album_user" on "album_user"."albumsId" = "album_asset"."albumsId"
where
"exif"."updatedAt" < now() - interval '1 millisecond'
"asset_exif"."updatedAt" < now() - interval '1 millisecond'
and (
"albums"."ownerId" = $1
or "album_users"."usersId" = $2
"album"."ownerId" = $1
or "album_user"."usersId" = $2
)
order by
"exif"."updateId" asc
"asset_exif"."updateId" asc
-- SyncRepository.albumToAsset.getBackfill
select
@ -193,7 +193,7 @@ select
"album_assets"."albumsId" as "albumId",
"album_assets"."updateId"
from
"albums_assets_assets" as "album_assets"
"album_asset" as "album_assets"
where
"album_assets"."albumsId" = $1
and "album_assets"."updatedAt" < now() - interval '1 millisecond'
@ -208,23 +208,23 @@ select
"assetId",
"albumId"
from
"album_assets_audit"
"album_asset_audit"
where
"albumId" in (
select
"id"
from
"albums"
"album"
where
"ownerId" = $1
union
(
select
"albumUsers"."albumsId" as "id"
"album_user"."albumsId" as "id"
from
"albums_shared_users_users" as "albumUsers"
"album_user"
where
"albumUsers"."usersId" = $2
"album_user"."usersId" = $2
)
)
and "deletedAt" < now() - interval '1 millisecond'
@ -233,30 +233,30 @@ order by
-- SyncRepository.albumToAsset.getUpserts
select
"album_assets"."assetsId" as "assetId",
"album_assets"."albumsId" as "albumId",
"album_assets"."updateId"
"album_asset"."assetsId" as "assetId",
"album_asset"."albumsId" as "albumId",
"album_asset"."updateId"
from
"albums_assets_assets" as "album_assets"
inner join "albums" on "albums"."id" = "album_assets"."albumsId"
left join "albums_shared_users_users" as "album_users" on "album_users"."albumsId" = "album_assets"."albumsId"
"album_asset"
inner join "album" on "album"."id" = "album_asset"."albumsId"
left join "album_user" on "album_user"."albumsId" = "album_asset"."albumsId"
where
"album_assets"."updatedAt" < now() - interval '1 millisecond'
"album_asset"."updatedAt" < now() - interval '1 millisecond'
and (
"albums"."ownerId" = $1
or "album_users"."usersId" = $2
"album"."ownerId" = $1
or "album_user"."usersId" = $2
)
order by
"album_assets"."updateId" asc
"album_asset"."updateId" asc
-- SyncRepository.albumUser.getBackfill
select
"album_users"."albumsId" as "albumId",
"album_users"."usersId" as "userId",
"album_users"."role",
"album_users"."updateId"
"album_user"."albumsId" as "albumId",
"album_user"."usersId" as "userId",
"album_user"."role",
"album_user"."updateId"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"albumsId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -271,23 +271,23 @@ select
"userId",
"albumId"
from
"album_users_audit"
"album_user_audit"
where
"albumId" in (
select
"id"
from
"albums"
"album"
where
"ownerId" = $1
union
(
select
"albumUsers"."albumsId" as "id"
"album_user"."albumsId" as "id"
from
"albums_shared_users_users" as "albumUsers"
"album_user"
where
"albumUsers"."usersId" = $2
"album_user"."usersId" = $2
)
)
and "deletedAt" < now() - interval '1 millisecond'
@ -296,19 +296,19 @@ order by
-- SyncRepository.albumUser.getUpserts
select
"album_users"."albumsId" as "albumId",
"album_users"."usersId" as "userId",
"album_users"."role",
"album_users"."updateId"
"album_user"."albumsId" as "albumId",
"album_user"."usersId" as "userId",
"album_user"."role",
"album_user"."updateId"
from
"albums_shared_users_users" as "album_users"
"album_user"
where
"album_users"."updatedAt" < now() - interval '1 millisecond'
and "album_users"."albumsId" in (
"album_user"."updatedAt" < now() - interval '1 millisecond'
and "album_user"."albumsId" in (
select
"id"
from
"albums"
"album"
where
"ownerId" = $1
union
@ -316,20 +316,20 @@ where
select
"albumUsers"."albumsId" as "id"
from
"albums_shared_users_users" as "albumUsers"
"album_user" as "albumUsers"
where
"albumUsers"."usersId" = $2
)
)
order by
"album_users"."updateId" asc
"album_user"."updateId" asc
-- SyncRepository.asset.getDeletes
select
"id",
"assetId"
from
"assets_audit"
"asset_audit"
where
"ownerId" = $1
and "deletedAt" < now() - interval '1 millisecond'
@ -338,22 +338,22 @@ order by
-- SyncRepository.asset.getUpserts
select
"assets"."id",
"assets"."ownerId",
"assets"."originalFileName",
"assets"."thumbhash",
"assets"."checksum",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."localDateTime",
"assets"."type",
"assets"."deletedAt",
"assets"."isFavorite",
"assets"."visibility",
"assets"."duration",
"assets"."updateId"
"asset"."id",
"asset"."ownerId",
"asset"."originalFileName",
"asset"."thumbhash",
"asset"."checksum",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."localDateTime",
"asset"."type",
"asset"."deletedAt",
"asset"."isFavorite",
"asset"."visibility",
"asset"."duration",
"asset"."updateId"
from
"assets"
"asset"
where
"ownerId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -362,40 +362,40 @@ order by
-- SyncRepository.assetExif.getUpserts
select
"exif"."assetId",
"exif"."description",
"exif"."exifImageWidth",
"exif"."exifImageHeight",
"exif"."fileSizeInByte",
"exif"."orientation",
"exif"."dateTimeOriginal",
"exif"."modifyDate",
"exif"."timeZone",
"exif"."latitude",
"exif"."longitude",
"exif"."projectionType",
"exif"."city",
"exif"."state",
"exif"."country",
"exif"."make",
"exif"."model",
"exif"."lensModel",
"exif"."fNumber",
"exif"."focalLength",
"exif"."iso",
"exif"."exposureTime",
"exif"."profileDescription",
"exif"."rating",
"exif"."fps",
"exif"."updateId"
"asset_exif"."assetId",
"asset_exif"."description",
"asset_exif"."exifImageWidth",
"asset_exif"."exifImageHeight",
"asset_exif"."fileSizeInByte",
"asset_exif"."orientation",
"asset_exif"."dateTimeOriginal",
"asset_exif"."modifyDate",
"asset_exif"."timeZone",
"asset_exif"."latitude",
"asset_exif"."longitude",
"asset_exif"."projectionType",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."lensModel",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."iso",
"asset_exif"."exposureTime",
"asset_exif"."profileDescription",
"asset_exif"."rating",
"asset_exif"."fps",
"asset_exif"."updateId"
from
"exif"
"asset_exif"
where
"assetId" in (
select
"id"
from
"assets"
"asset"
where
"ownerId" = $1
)
@ -408,7 +408,7 @@ select
"id",
"memoryId"
from
"memories_audit"
"memory_audit"
where
"userId" = $1
and "deletedAt" < now() - interval '1 millisecond'
@ -431,7 +431,7 @@ select
"hideAt",
"updateId"
from
"memories"
"memory"
where
"ownerId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -444,13 +444,13 @@ select
"memoryId",
"assetId"
from
"memory_assets_audit"
"memory_asset_audit"
where
"memoryId" in (
select
"id"
from
"memories"
"memory"
where
"ownerId" = $1
)
@ -464,13 +464,13 @@ select
"assetsId" as "assetId",
"updateId"
from
"memories_assets_assets"
"memory_asset"
where
"memoriesId" in (
select
"id"
from
"memories"
"memory"
where
"ownerId" = $1
)
@ -483,13 +483,13 @@ select
"sharedById",
"createId"
from
"partners"
"partner"
where
"sharedWithId" = $1
and "createId" >= $2
and "createdAt" < now() - interval '1 millisecond'
order by
"partners"."createId" asc
"partner"."createId" asc
-- SyncRepository.partner.getDeletes
select
@ -497,7 +497,7 @@ select
"sharedById",
"sharedWithId"
from
"partners_audit"
"partner_audit"
where
(
"sharedById" = $1
@ -514,7 +514,7 @@ select
"inTimeline",
"updateId"
from
"partners"
"partner"
where
(
"sharedById" = $1
@ -526,22 +526,22 @@ order by
-- SyncRepository.partnerAsset.getBackfill
select
"assets"."id",
"assets"."ownerId",
"assets"."originalFileName",
"assets"."thumbhash",
"assets"."checksum",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."localDateTime",
"assets"."type",
"assets"."deletedAt",
"assets"."isFavorite",
"assets"."visibility",
"assets"."duration",
"assets"."updateId"
"asset"."id",
"asset"."ownerId",
"asset"."originalFileName",
"asset"."thumbhash",
"asset"."checksum",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."localDateTime",
"asset"."type",
"asset"."deletedAt",
"asset"."isFavorite",
"asset"."visibility",
"asset"."duration",
"asset"."updateId"
from
"assets"
"asset"
where
"ownerId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -555,13 +555,13 @@ select
"id",
"assetId"
from
"assets_audit"
"asset_audit"
where
"ownerId" in (
select
"sharedById"
from
"partners"
"partner"
where
"sharedWithId" = $1
)
@ -571,28 +571,28 @@ order by
-- SyncRepository.partnerAsset.getUpserts
select
"assets"."id",
"assets"."ownerId",
"assets"."originalFileName",
"assets"."thumbhash",
"assets"."checksum",
"assets"."fileCreatedAt",
"assets"."fileModifiedAt",
"assets"."localDateTime",
"assets"."type",
"assets"."deletedAt",
"assets"."isFavorite",
"assets"."visibility",
"assets"."duration",
"assets"."updateId"
"asset"."id",
"asset"."ownerId",
"asset"."originalFileName",
"asset"."thumbhash",
"asset"."checksum",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."localDateTime",
"asset"."type",
"asset"."deletedAt",
"asset"."isFavorite",
"asset"."visibility",
"asset"."duration",
"asset"."updateId"
from
"assets"
"asset"
where
"ownerId" in (
select
"sharedById"
from
"partners"
"partner"
where
"sharedWithId" = $1
)
@ -602,85 +602,85 @@ order by
-- SyncRepository.partnerAssetExif.getBackfill
select
"exif"."assetId",
"exif"."description",
"exif"."exifImageWidth",
"exif"."exifImageHeight",
"exif"."fileSizeInByte",
"exif"."orientation",
"exif"."dateTimeOriginal",
"exif"."modifyDate",
"exif"."timeZone",
"exif"."latitude",
"exif"."longitude",
"exif"."projectionType",
"exif"."city",
"exif"."state",
"exif"."country",
"exif"."make",
"exif"."model",
"exif"."lensModel",
"exif"."fNumber",
"exif"."focalLength",
"exif"."iso",
"exif"."exposureTime",
"exif"."profileDescription",
"exif"."rating",
"exif"."fps",
"exif"."updateId"
"asset_exif"."assetId",
"asset_exif"."description",
"asset_exif"."exifImageWidth",
"asset_exif"."exifImageHeight",
"asset_exif"."fileSizeInByte",
"asset_exif"."orientation",
"asset_exif"."dateTimeOriginal",
"asset_exif"."modifyDate",
"asset_exif"."timeZone",
"asset_exif"."latitude",
"asset_exif"."longitude",
"asset_exif"."projectionType",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."lensModel",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."iso",
"asset_exif"."exposureTime",
"asset_exif"."profileDescription",
"asset_exif"."rating",
"asset_exif"."fps",
"asset_exif"."updateId"
from
"exif"
inner join "assets" on "assets"."id" = "exif"."assetId"
"asset_exif"
inner join "asset" on "asset"."id" = "asset_exif"."assetId"
where
"assets"."ownerId" = $1
and "exif"."updatedAt" < now() - interval '1 millisecond'
and "exif"."updateId" <= $2
and "exif"."updateId" >= $3
"asset"."ownerId" = $1
and "asset_exif"."updatedAt" < now() - interval '1 millisecond'
and "asset_exif"."updateId" <= $2
and "asset_exif"."updateId" >= $3
order by
"exif"."updateId" asc
"asset_exif"."updateId" asc
-- SyncRepository.partnerAssetExif.getUpserts
select
"exif"."assetId",
"exif"."description",
"exif"."exifImageWidth",
"exif"."exifImageHeight",
"exif"."fileSizeInByte",
"exif"."orientation",
"exif"."dateTimeOriginal",
"exif"."modifyDate",
"exif"."timeZone",
"exif"."latitude",
"exif"."longitude",
"exif"."projectionType",
"exif"."city",
"exif"."state",
"exif"."country",
"exif"."make",
"exif"."model",
"exif"."lensModel",
"exif"."fNumber",
"exif"."focalLength",
"exif"."iso",
"exif"."exposureTime",
"exif"."profileDescription",
"exif"."rating",
"exif"."fps",
"exif"."updateId"
"asset_exif"."assetId",
"asset_exif"."description",
"asset_exif"."exifImageWidth",
"asset_exif"."exifImageHeight",
"asset_exif"."fileSizeInByte",
"asset_exif"."orientation",
"asset_exif"."dateTimeOriginal",
"asset_exif"."modifyDate",
"asset_exif"."timeZone",
"asset_exif"."latitude",
"asset_exif"."longitude",
"asset_exif"."projectionType",
"asset_exif"."city",
"asset_exif"."state",
"asset_exif"."country",
"asset_exif"."make",
"asset_exif"."model",
"asset_exif"."lensModel",
"asset_exif"."fNumber",
"asset_exif"."focalLength",
"asset_exif"."iso",
"asset_exif"."exposureTime",
"asset_exif"."profileDescription",
"asset_exif"."rating",
"asset_exif"."fps",
"asset_exif"."updateId"
from
"exif"
"asset_exif"
where
"assetId" in (
select
"id"
from
"assets"
"asset"
where
"ownerId" in (
select
"sharedById"
from
"partners"
"partner"
where
"sharedWithId" = $1
)
@ -694,13 +694,13 @@ select
"id",
"stackId"
from
"stacks_audit"
"stack_audit"
where
"userId" in (
select
"sharedById"
from
"partners"
"partner"
where
"sharedWithId" = $1
)
@ -710,14 +710,14 @@ order by
-- SyncRepository.partnerStack.getBackfill
select
"asset_stack"."id",
"asset_stack"."createdAt",
"asset_stack"."updatedAt",
"asset_stack"."primaryAssetId",
"asset_stack"."ownerId",
"stack"."id",
"stack"."createdAt",
"stack"."updatedAt",
"stack"."primaryAssetId",
"stack"."ownerId",
"updateId"
from
"asset_stack"
"stack"
where
"ownerId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -728,20 +728,20 @@ order by
-- SyncRepository.partnerStack.getUpserts
select
"asset_stack"."id",
"asset_stack"."createdAt",
"asset_stack"."updatedAt",
"asset_stack"."primaryAssetId",
"asset_stack"."ownerId",
"stack"."id",
"stack"."createdAt",
"stack"."updatedAt",
"stack"."primaryAssetId",
"stack"."ownerId",
"updateId"
from
"asset_stack"
"stack"
where
"ownerId" in (
select
"sharedById"
from
"partners"
"partner"
where
"sharedWithId" = $1
)
@ -788,7 +788,7 @@ select
"id",
"stackId"
from
"stacks_audit"
"stack_audit"
where
"userId" = $1
and "deletedAt" < now() - interval '1 millisecond'
@ -797,14 +797,14 @@ order by
-- SyncRepository.stack.getUpserts
select
"asset_stack"."id",
"asset_stack"."createdAt",
"asset_stack"."updatedAt",
"asset_stack"."primaryAssetId",
"asset_stack"."ownerId",
"stack"."id",
"stack"."createdAt",
"stack"."updatedAt",
"stack"."primaryAssetId",
"stack"."ownerId",
"updateId"
from
"asset_stack"
"stack"
where
"ownerId" = $1
and "updatedAt" < now() - interval '1 millisecond'
@ -816,7 +816,7 @@ select
"id",
"userId"
from
"users_audit"
"user_audit"
where
"deletedAt" < now() - interval '1 millisecond'
order by
@ -830,7 +830,7 @@ select
"deletedAt",
"updateId"
from
"users"
"user"
where
"updatedAt" < now() - interval '1 millisecond'
order by

View File

@ -2,27 +2,27 @@
-- TagRepository.get
select
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tags"
"tag"
where
"id" = $1
-- TagRepository.getByValue
select
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tags"
"tag"
where
"userId" = $1
and "value" = $2
@ -30,31 +30,31 @@ where
-- TagRepository.upsertValue
begin
insert into
"tags" ("userId", "value", "parentId")
"tag" ("userId", "value", "parentId")
values
($1, $2, $3)
on conflict ("userId", "value") do update
set
"parentId" = $4
returning
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
rollback
-- TagRepository.getAll
select
"tags"."id",
"tags"."value",
"tags"."createdAt",
"tags"."updatedAt",
"tags"."color",
"tags"."parentId"
"tag"."id",
"tag"."value",
"tag"."createdAt",
"tag"."updatedAt",
"tag"."color",
"tag"."parentId"
from
"tags"
"tag"
where
"userId" = $1
order by
@ -62,14 +62,14 @@ order by
-- TagRepository.create
insert into
"tags" ("userId", "color", "value")
"tag" ("userId", "color", "value")
values
($1, $2, $3)
returning
*
-- TagRepository.update
update "tags"
update "tag"
set
"color" = $1
where
@ -78,7 +78,7 @@ returning
*
-- TagRepository.delete
delete from "tags"
delete from "tag"
where
"id" = $1

View File

@ -1,7 +1,7 @@
-- NOTE: This file is auto generated by ./sql-generator
-- TrashRepository.restore
update "assets"
update "asset"
set
"status" = $1,
"deletedAt" = $2
@ -10,7 +10,7 @@ where
and "status" = $4
-- TrashRepository.empty
update "assets"
update "asset"
set
"status" = $1
where
@ -18,7 +18,7 @@ where
and "status" = $3
-- TrashRepository.restoreAll
update "assets"
update "asset"
set
"status" = $1,
"deletedAt" = $2

View File

@ -30,14 +30,14 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
where
"users"."id" = $1
and "users"."deletedAt" is null
"user"."id" = $1
and "user"."deletedAt" is null
-- UserRepository.getAdmin
select
@ -69,43 +69,43 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
where
"users"."isAdmin" = $1
and "users"."deletedAt" is null
"user"."isAdmin" = $1
and "user"."deletedAt" is null
-- UserRepository.hasAdmin
select
"users"."id"
"user"."id"
from
"users"
"user"
where
"users"."isAdmin" = $1
and "users"."deletedAt" is null
"user"."isAdmin" = $1
and "user"."deletedAt" is null
-- UserRepository.getForPinCode
select
"users"."pinCode",
"users"."password"
"user"."pinCode",
"user"."password"
from
"users"
"user"
where
"users"."id" = $1
and "users"."deletedAt" is null
"user"."id" = $1
and "user"."deletedAt" is null
-- UserRepository.getForChangePassword
select
"users"."id",
"users"."password"
"user"."id",
"user"."password"
from
"users"
"user"
where
"users"."id" = $1
and "users"."deletedAt" is null
"user"."id" = $1
and "user"."deletedAt" is null
-- UserRepository.getByEmail
select
@ -137,14 +137,14 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
where
"email" = $1
and "users"."deletedAt" is null
and "user"."deletedAt" is null
-- UserRepository.getByStorageLabel
select
@ -166,10 +166,10 @@ select
"quotaSizeInBytes",
"quotaUsageInBytes"
from
"users"
"user"
where
"users"."storageLabel" = $1
and "users"."deletedAt" is null
"user"."storageLabel" = $1
and "user"."deletedAt" is null
-- UserRepository.getByOAuthId
select
@ -201,22 +201,22 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
where
"users"."oauthId" = $1
and "users"."deletedAt" is null
"user"."oauthId" = $1
and "user"."deletedAt" is null
-- UserRepository.getDeletedAfter
select
"id"
from
"users"
"user"
where
"users"."deletedAt" < $1
"user"."deletedAt" < $1
-- UserRepository.getList (with deleted)
select
@ -248,11 +248,11 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
order by
"createdAt" desc
@ -286,95 +286,95 @@ select
from
"user_metadata"
where
"users"."id" = "user_metadata"."userId"
"user"."id" = "user_metadata"."userId"
) as agg
) as "metadata"
from
"users"
"user"
where
"users"."deletedAt" is null
"user"."deletedAt" is null
order by
"createdAt" desc
-- UserRepository.getUserStats
select
"users"."id" as "userId",
"users"."name" as "userName",
"users"."quotaSizeInBytes",
"user"."id" as "userId",
"user"."name" as "userName",
"user"."quotaSizeInBytes",
count(*) filter (
where
(
"assets"."type" = 'IMAGE'
and "assets"."visibility" != 'hidden'
"asset"."type" = 'IMAGE'
and "asset"."visibility" != 'hidden'
)
) as "photos",
count(*) filter (
where
(
"assets"."type" = 'VIDEO'
and "assets"."visibility" != 'hidden'
"asset"."type" = 'VIDEO'
and "asset"."visibility" != 'hidden'
)
) as "videos",
coalesce(
sum("exif"."fileSizeInByte") filter (
sum("asset_exif"."fileSizeInByte") filter (
where
"assets"."libraryId" is null
"asset"."libraryId" is null
),
0
) as "usage",
coalesce(
sum("exif"."fileSizeInByte") filter (
sum("asset_exif"."fileSizeInByte") filter (
where
(
"assets"."libraryId" is null
and "assets"."type" = 'IMAGE'
"asset"."libraryId" is null
and "asset"."type" = 'IMAGE'
)
),
0
) as "usagePhotos",
coalesce(
sum("exif"."fileSizeInByte") filter (
sum("asset_exif"."fileSizeInByte") filter (
where
(
"assets"."libraryId" is null
and "assets"."type" = 'VIDEO'
"asset"."libraryId" is null
and "asset"."type" = 'VIDEO'
)
),
0
) as "usageVideos"
from
"users"
left join "assets" on "assets"."ownerId" = "users"."id"
and "assets"."deletedAt" is null
left join "exif" on "exif"."assetId" = "assets"."id"
"user"
left join "asset" on "asset"."ownerId" = "user"."id"
and "asset"."deletedAt" is null
left join "asset_exif" on "asset_exif"."assetId" = "asset"."id"
group by
"users"."id"
"user"."id"
order by
"users"."createdAt" asc
"user"."createdAt" asc
-- UserRepository.updateUsage
update "users"
update "user"
set
"quotaUsageInBytes" = "quotaUsageInBytes" + $1,
"updatedAt" = $2
where
"id" = $3::uuid
and "users"."deletedAt" is null
and "user"."deletedAt" is null
-- UserRepository.syncUsage
update "users"
update "user"
set
"quotaUsageInBytes" = (
select
coalesce(sum("exif"."fileSizeInByte"), 0) as "usage"
coalesce(sum("asset_exif"."fileSizeInByte"), 0) as "usage"
from
"assets"
left join "exif" on "exif"."assetId" = "assets"."id"
"asset"
left join "asset_exif" on "asset_exif"."assetId" = "asset"."id"
where
"assets"."libraryId" is null
and "assets"."ownerId" = "users"."id"
"asset"."libraryId" is null
and "asset"."ownerId" = "user"."id"
),
"updatedAt" = $1
where
"users"."deletedAt" is null
and "users"."id" = $2::uuid
"user"."deletedAt" is null
and "user"."id" = $2::uuid

View File

@ -2,9 +2,9 @@
-- ViewRepository.getUniqueOriginalPaths
select distinct
substring("assets"."originalPath", $1) as "directoryPath"
substring("asset"."originalPath", $1) as "directoryPath"
from
"assets"
"asset"
where
"ownerId" = $2::uuid
and "visibility" = $3
@ -15,11 +15,11 @@ where
-- ViewRepository.getAssetsByOriginalPath
select
"assets".*,
to_json("exif") as "exifInfo"
"asset".*,
to_json("asset_exif") as "exifInfo"
from
"assets"
left join "exif" on "assets"."id" = "exif"."assetId"
"asset"
left join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
where
"ownerId" = $1::uuid
and "visibility" = $2
@ -30,4 +30,4 @@ where
and "originalPath" like $3
and "originalPath" not like $4
order by
regexp_replace("assets"."originalPath", $5, $6) asc
regexp_replace("asset"."originalPath", $5, $6) asc

View File

@ -35,9 +35,9 @@ class ActivityAccess {
return this.db
.selectFrom('activity')
.select('activity.id')
.leftJoin('albums', (join) => join.onRef('activity.albumId', '=', 'albums.id').on('albums.deletedAt', 'is', null))
.leftJoin('album', (join) => join.onRef('activity.albumId', '=', 'album.id').on('album.deletedAt', 'is', null))
.where('activity.id', 'in', [...activityIds])
.whereRef('albums.ownerId', '=', asUuid(userId))
.whereRef('album.ownerId', '=', asUuid(userId))
.execute()
.then((activities) => new Set(activities.map((activity) => activity.id)));
}
@ -50,14 +50,14 @@ class ActivityAccess {
}
return this.db
.selectFrom('albums')
.select('albums.id')
.leftJoin('albums_shared_users_users as albumUsers', 'albumUsers.albumsId', 'albums.id')
.leftJoin('users', (join) => join.onRef('users.id', '=', 'albumUsers.usersId').on('users.deletedAt', 'is', null))
.where('albums.id', 'in', [...albumIds])
.where('albums.isActivityEnabled', '=', true)
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('users.id', '=', userId)]))
.where('albums.deletedAt', 'is', null)
.selectFrom('album')
.select('album.id')
.leftJoin('album_user as albumUsers', 'albumUsers.albumsId', 'album.id')
.leftJoin('user', (join) => join.onRef('user.id', '=', 'albumUsers.usersId').on('user.deletedAt', 'is', null))
.where('album.id', 'in', [...albumIds])
.where('album.isActivityEnabled', '=', true)
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('user.id', '=', userId)]))
.where('album.deletedAt', 'is', null)
.execute()
.then((albums) => new Set(albums.map((album) => album.id)));
}
@ -74,11 +74,11 @@ class AlbumAccess {
}
return this.db
.selectFrom('albums')
.select('albums.id')
.where('albums.id', 'in', [...albumIds])
.where('albums.ownerId', '=', userId)
.where('albums.deletedAt', 'is', null)
.selectFrom('album')
.select('album.id')
.where('album.id', 'in', [...albumIds])
.where('album.ownerId', '=', userId)
.where('album.deletedAt', 'is', null)
.execute()
.then((albums) => new Set(albums.map((album) => album.id)));
}
@ -94,14 +94,14 @@ class AlbumAccess {
access === AlbumUserRole.EDITOR ? [AlbumUserRole.EDITOR] : [AlbumUserRole.EDITOR, AlbumUserRole.VIEWER];
return this.db
.selectFrom('albums')
.select('albums.id')
.leftJoin('albums_shared_users_users as albumUsers', 'albumUsers.albumsId', 'albums.id')
.leftJoin('users', (join) => join.onRef('users.id', '=', 'albumUsers.usersId').on('users.deletedAt', 'is', null))
.where('albums.id', 'in', [...albumIds])
.where('albums.deletedAt', 'is', null)
.where('users.id', '=', userId)
.where('albumUsers.role', 'in', [...accessRole])
.selectFrom('album')
.select('album.id')
.leftJoin('album_user', 'album_user.albumsId', 'album.id')
.leftJoin('user', (join) => join.onRef('user.id', '=', 'album_user.usersId').on('user.deletedAt', 'is', null))
.where('album.id', 'in', [...albumIds])
.where('album.deletedAt', 'is', null)
.where('user.id', '=', userId)
.where('album_user.role', 'in', [...accessRole])
.execute()
.then((albums) => new Set(albums.map((album) => album.id)));
}
@ -114,10 +114,10 @@ class AlbumAccess {
}
return this.db
.selectFrom('shared_links')
.select('shared_links.albumId')
.where('shared_links.id', '=', sharedLinkId)
.where('shared_links.albumId', 'in', [...albumIds])
.selectFrom('shared_link')
.select('shared_link.albumId')
.where('shared_link.id', '=', sharedLinkId)
.where('shared_link.albumId', 'in', [...albumIds])
.execute()
.then(
(sharedLinks) => new Set(sharedLinks.flatMap((sharedLink) => (sharedLink.albumId ? [sharedLink.albumId] : []))),
@ -136,21 +136,21 @@ class AssetAccess {
}
return this.db
.selectFrom('albums')
.innerJoin('albums_assets_assets as albumAssets', 'albums.id', 'albumAssets.albumsId')
.innerJoin('assets', (join) =>
join.onRef('assets.id', '=', 'albumAssets.assetsId').on('assets.deletedAt', 'is', null),
.selectFrom('album')
.innerJoin('album_asset as albumAssets', 'album.id', 'albumAssets.albumsId')
.innerJoin('asset', (join) =>
join.onRef('asset.id', '=', 'albumAssets.assetsId').on('asset.deletedAt', 'is', null),
)
.leftJoin('albums_shared_users_users as albumUsers', 'albumUsers.albumsId', 'albums.id')
.leftJoin('users', (join) => join.onRef('users.id', '=', 'albumUsers.usersId').on('users.deletedAt', 'is', null))
.select(['assets.id', 'assets.livePhotoVideoId'])
.leftJoin('album_user as albumUsers', 'albumUsers.albumsId', 'album.id')
.leftJoin('user', (join) => join.onRef('user.id', '=', 'albumUsers.usersId').on('user.deletedAt', 'is', null))
.select(['asset.id', 'asset.livePhotoVideoId'])
.where(
sql`array["assets"."id", "assets"."livePhotoVideoId"]`,
sql`array["asset"."id", "asset"."livePhotoVideoId"]`,
'&&',
sql`array[${sql.join([...assetIds])}]::uuid[] `,
)
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('users.id', '=', userId)]))
.where('albums.deletedAt', 'is', null)
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('user.id', '=', userId)]))
.where('album.deletedAt', 'is', null)
.execute()
.then((assets) => {
const allowedIds = new Set<string>();
@ -174,11 +174,11 @@ class AssetAccess {
}
return this.db
.selectFrom('assets')
.select('assets.id')
.where('assets.id', 'in', [...assetIds])
.where('assets.ownerId', '=', userId)
.$if(!hasElevatedPermission, (eb) => eb.where('assets.visibility', '!=', AssetVisibility.LOCKED))
.selectFrom('asset')
.select('asset.id')
.where('asset.id', 'in', [...assetIds])
.where('asset.ownerId', '=', userId)
.$if(!hasElevatedPermission, (eb) => eb.where('asset.visibility', '!=', AssetVisibility.LOCKED))
.execute()
.then((assets) => new Set(assets.map((asset) => asset.id)));
}
@ -191,23 +191,21 @@ class AssetAccess {
}
return this.db
.selectFrom('partners as partner')
.innerJoin('users as sharedBy', (join) =>
.selectFrom('partner')
.innerJoin('user as sharedBy', (join) =>
join.onRef('sharedBy.id', '=', 'partner.sharedById').on('sharedBy.deletedAt', 'is', null),
)
.innerJoin('assets', (join) =>
join.onRef('assets.ownerId', '=', 'sharedBy.id').on('assets.deletedAt', 'is', null),
)
.select('assets.id')
.innerJoin('asset', (join) => join.onRef('asset.ownerId', '=', 'sharedBy.id').on('asset.deletedAt', 'is', null))
.select('asset.id')
.where('partner.sharedWithId', '=', userId)
.where((eb) =>
eb.or([
eb('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE)),
eb('assets.visibility', '=', sql.lit(AssetVisibility.HIDDEN)),
eb('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE)),
eb('asset.visibility', '=', sql.lit(AssetVisibility.HIDDEN)),
]),
)
.where('assets.id', 'in', [...assetIds])
.where('asset.id', 'in', [...assetIds])
.execute()
.then((assets) => new Set(assets.map((asset) => asset.id)));
}
@ -220,27 +218,25 @@ class AssetAccess {
}
return this.db
.selectFrom('shared_links')
.leftJoin('albums', (join) =>
join.onRef('albums.id', '=', 'shared_links.albumId').on('albums.deletedAt', 'is', null),
.selectFrom('shared_link')
.leftJoin('album', (join) => join.onRef('album.id', '=', 'shared_link.albumId').on('album.deletedAt', 'is', null))
.leftJoin('shared_link_asset', 'shared_link_asset.sharedLinksId', 'shared_link.id')
.leftJoin('asset', (join) =>
join.onRef('asset.id', '=', 'shared_link_asset.assetsId').on('asset.deletedAt', 'is', null),
)
.leftJoin('shared_link__asset', 'shared_link__asset.sharedLinksId', 'shared_links.id')
.leftJoin('assets', (join) =>
join.onRef('assets.id', '=', 'shared_link__asset.assetsId').on('assets.deletedAt', 'is', null),
)
.leftJoin('albums_assets_assets', 'albums_assets_assets.albumsId', 'albums.id')
.leftJoin('assets as albumAssets', (join) =>
join.onRef('albumAssets.id', '=', 'albums_assets_assets.assetsId').on('albumAssets.deletedAt', 'is', null),
.leftJoin('album_asset', 'album_asset.albumsId', 'album.id')
.leftJoin('asset as albumAssets', (join) =>
join.onRef('albumAssets.id', '=', 'album_asset.assetsId').on('albumAssets.deletedAt', 'is', null),
)
.select([
'assets.id as assetId',
'assets.livePhotoVideoId as assetLivePhotoVideoId',
'asset.id as assetId',
'asset.livePhotoVideoId as assetLivePhotoVideoId',
'albumAssets.id as albumAssetId',
'albumAssets.livePhotoVideoId as albumAssetLivePhotoVideoId',
])
.where('shared_links.id', '=', sharedLinkId)
.where('shared_link.id', '=', sharedLinkId)
.where(
sql`array["assets"."id", "assets"."livePhotoVideoId", "albumAssets"."id", "albumAssets"."livePhotoVideoId"]`,
sql`array["asset"."id", "asset"."livePhotoVideoId", "albumAssets"."id", "albumAssets"."livePhotoVideoId"]`,
'&&',
sql`array[${sql.join([...assetIds])}]::uuid[] `,
)
@ -277,10 +273,10 @@ class AuthDeviceAccess {
}
return this.db
.selectFrom('sessions')
.select('sessions.id')
.where('sessions.userId', '=', userId)
.where('sessions.id', 'in', [...deviceIds])
.selectFrom('session')
.select('session.id')
.where('session.userId', '=', userId)
.where('session.id', 'in', [...deviceIds])
.execute()
.then((tokens) => new Set(tokens.map((token) => token.id)));
}
@ -297,10 +293,10 @@ class NotificationAccess {
}
return this.db
.selectFrom('notifications')
.select('notifications.id')
.where('notifications.id', 'in', [...notificationIds])
.where('notifications.userId', '=', userId)
.selectFrom('notification')
.select('notification.id')
.where('notification.id', 'in', [...notificationIds])
.where('notification.userId', '=', userId)
.execute()
.then((stacks) => new Set(stacks.map((stack) => stack.id)));
}
@ -317,10 +313,10 @@ class SessionAccess {
}
return this.db
.selectFrom('sessions')
.select('sessions.id')
.where('sessions.id', 'in', [...sessionIds])
.where('sessions.userId', '=', userId)
.selectFrom('session')
.select('session.id')
.where('session.id', 'in', [...sessionIds])
.where('session.userId', '=', userId)
.execute()
.then((sessions) => new Set(sessions.map((session) => session.id)));
}
@ -336,10 +332,10 @@ class StackAccess {
}
return this.db
.selectFrom('asset_stack as stacks')
.select('stacks.id')
.where('stacks.id', 'in', [...stackIds])
.where('stacks.ownerId', '=', userId)
.selectFrom('stack')
.select('stack.id')
.where('stack.id', 'in', [...stackIds])
.where('stack.ownerId', '=', userId)
.execute()
.then((stacks) => new Set(stacks.map((stack) => stack.id)));
}
@ -356,10 +352,10 @@ class TimelineAccess {
}
return this.db
.selectFrom('partners')
.select('partners.sharedById')
.where('partners.sharedById', 'in', [...partnerIds])
.where('partners.sharedWithId', '=', userId)
.selectFrom('partner')
.select('partner.sharedById')
.where('partner.sharedById', 'in', [...partnerIds])
.where('partner.sharedWithId', '=', userId)
.execute()
.then((partners) => new Set(partners.map((partner) => partner.sharedById)));
}
@ -376,11 +372,11 @@ class MemoryAccess {
}
return this.db
.selectFrom('memories')
.select('memories.id')
.where('memories.id', 'in', [...memoryIds])
.where('memories.ownerId', '=', userId)
.where('memories.deletedAt', 'is', null)
.selectFrom('memory')
.select('memory.id')
.where('memory.id', 'in', [...memoryIds])
.where('memory.ownerId', '=', userId)
.where('memory.deletedAt', 'is', null)
.execute()
.then((memories) => new Set(memories.map((memory) => memory.id)));
}
@ -413,13 +409,11 @@ class PersonAccess {
}
return this.db
.selectFrom('asset_faces')
.select('asset_faces.id')
.leftJoin('assets', (join) =>
join.onRef('assets.id', '=', 'asset_faces.assetId').on('assets.deletedAt', 'is', null),
)
.where('asset_faces.id', 'in', [...assetFaceIds])
.where('assets.ownerId', '=', userId)
.selectFrom('asset_face')
.select('asset_face.id')
.leftJoin('asset', (join) => join.onRef('asset.id', '=', 'asset_face.assetId').on('asset.deletedAt', 'is', null))
.where('asset_face.id', 'in', [...assetFaceIds])
.where('asset.ownerId', '=', userId)
.execute()
.then((faces) => new Set(faces.map((face) => face.id)));
}
@ -436,10 +430,10 @@ class PartnerAccess {
}
return this.db
.selectFrom('partners')
.select('partners.sharedById')
.where('partners.sharedById', 'in', [...partnerIds])
.where('partners.sharedWithId', '=', userId)
.selectFrom('partner')
.select('partner.sharedById')
.where('partner.sharedById', 'in', [...partnerIds])
.where('partner.sharedWithId', '=', userId)
.execute()
.then((partners) => new Set(partners.map((partner) => partner.sharedById)));
}
@ -456,10 +450,10 @@ class TagAccess {
}
return this.db
.selectFrom('tags')
.select('tags.id')
.where('tags.id', 'in', [...tagIds])
.where('tags.userId', '=', userId)
.selectFrom('tag')
.select('tag.id')
.where('tag.id', 'in', [...tagIds])
.where('tag.userId', '=', userId)
.execute()
.then((tags) => new Set(tags.map((tag) => tag.id)));
}

View File

@ -27,7 +27,9 @@ export class ActivityRepository {
return this.db
.selectFrom('activity')
.selectAll('activity')
.innerJoin('users', (join) => join.onRef('users.id', '=', 'activity.userId').on('users.deletedAt', 'is', null))
.innerJoin('user as user2', (join) =>
join.onRef('user2.id', '=', 'activity.userId').on('user2.deletedAt', 'is', null),
)
.innerJoinLateral(
(eb) =>
eb
@ -37,13 +39,13 @@ export class ActivityRepository {
(join) => join.onTrue(),
)
.select((eb) => eb.fn.toJson('user').as('user'))
.leftJoin('assets', 'assets.id', 'activity.assetId')
.leftJoin('asset', 'asset.id', 'activity.assetId')
.$if(!!userId, (qb) => qb.where('activity.userId', '=', userId!))
.$if(assetId === null, (qb) => qb.where('assetId', 'is', null))
.$if(!!assetId, (qb) => qb.where('activity.assetId', '=', assetId!))
.$if(!!albumId, (qb) => qb.where('activity.albumId', '=', albumId!))
.$if(isLiked !== undefined, (qb) => qb.where('activity.isLiked', '=', isLiked!))
.where('assets.deletedAt', 'is', null)
.where('asset.deletedAt', 'is', null)
.orderBy('activity.createdAt', 'asc')
.execute();
}
@ -55,7 +57,7 @@ export class ActivityRepository {
.values(activity)
.returningAll()
.returning((eb) =>
jsonObjectFrom(eb.selectFrom('users').whereRef('users.id', '=', 'activity.userId').select(columns.user)).as(
jsonObjectFrom(eb.selectFrom('user').whereRef('user.id', '=', 'activity.userId').select(columns.user)).as(
'user',
),
)
@ -82,14 +84,14 @@ export class ActivityRepository {
eb.fn.countAll<number>().filterWhere('activity.isLiked', '=', false).as('comments'),
eb.fn.countAll<number>().filterWhere('activity.isLiked', '=', true).as('likes'),
])
.innerJoin('users', (join) => join.onRef('users.id', '=', 'activity.userId').on('users.deletedAt', 'is', null))
.leftJoin('assets', 'assets.id', 'activity.assetId')
.innerJoin('user', (join) => join.onRef('user.id', '=', 'activity.userId').on('user.deletedAt', 'is', null))
.leftJoin('asset', 'asset.id', 'activity.assetId')
.$if(!!assetId, (qb) => qb.where('activity.assetId', '=', assetId!))
.where('activity.albumId', '=', albumId)
.where(({ or, and, eb }) =>
or([
and([eb('assets.deletedAt', 'is', null), eb('assets.visibility', '!=', sql.lit(AssetVisibility.LOCKED))]),
eb('assets.id', 'is', null),
and([eb('asset.deletedAt', 'is', null), eb('asset.visibility', '!=', sql.lit(AssetVisibility.LOCKED))]),
eb('asset.id', 'is', null),
]),
)
.executeTakeFirstOrThrow();

View File

@ -18,7 +18,7 @@ export class AlbumUserRepository {
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] })
create(albumUser: Insertable<AlbumUserTable>) {
return this.db
.insertInto('albums_shared_users_users')
.insertInto('album_user')
.values(albumUser)
.returning(['usersId', 'albumsId', 'role'])
.executeTakeFirstOrThrow();
@ -27,7 +27,7 @@ export class AlbumUserRepository {
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] })
update({ usersId, albumsId }: AlbumPermissionId, dto: Updateable<AlbumUserTable>) {
return this.db
.updateTable('albums_shared_users_users')
.updateTable('album_user')
.set(dto)
.where('usersId', '=', usersId)
.where('albumsId', '=', albumsId)
@ -37,10 +37,6 @@ export class AlbumUserRepository {
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] })
async delete({ usersId, albumsId }: AlbumPermissionId): Promise<void> {
await this.db
.deleteFrom('albums_shared_users_users')
.where('usersId', '=', usersId)
.where('albumsId', '=', albumsId)
.execute();
await this.db.deleteFrom('album_user').where('usersId', '=', usersId).where('albumsId', '=', albumsId).execute();
}
}

View File

@ -21,47 +21,47 @@ export interface AlbumInfoOptions {
withAssets: boolean;
}
const withOwner = (eb: ExpressionBuilder<DB, 'albums'>) => {
return jsonObjectFrom(eb.selectFrom('users').select(columns.user).whereRef('users.id', '=', 'albums.ownerId'))
const withOwner = (eb: ExpressionBuilder<DB, 'album'>) => {
return jsonObjectFrom(eb.selectFrom('user').select(columns.user).whereRef('user.id', '=', 'album.ownerId'))
.$notNull()
.as('owner');
};
const withAlbumUsers = (eb: ExpressionBuilder<DB, 'albums'>) => {
const withAlbumUsers = (eb: ExpressionBuilder<DB, 'album'>) => {
return jsonArrayFrom(
eb
.selectFrom('albums_shared_users_users as album_users')
.select('album_users.role')
.selectFrom('album_user')
.select('album_user.role')
.select((eb) =>
jsonObjectFrom(eb.selectFrom('users').select(columns.user).whereRef('users.id', '=', 'album_users.usersId'))
jsonObjectFrom(eb.selectFrom('user').select(columns.user).whereRef('user.id', '=', 'album_user.usersId'))
.$notNull()
.as('user'),
)
.whereRef('album_users.albumsId', '=', 'albums.id'),
.whereRef('album_user.albumsId', '=', 'album.id'),
)
.$notNull()
.as('albumUsers');
};
const withSharedLink = (eb: ExpressionBuilder<DB, 'albums'>) => {
return jsonArrayFrom(eb.selectFrom('shared_links').selectAll().whereRef('shared_links.albumId', '=', 'albums.id')).as(
const withSharedLink = (eb: ExpressionBuilder<DB, 'album'>) => {
return jsonArrayFrom(eb.selectFrom('shared_link').selectAll().whereRef('shared_link.albumId', '=', 'album.id')).as(
'sharedLinks',
);
};
const withAssets = (eb: ExpressionBuilder<DB, 'albums'>) => {
const withAssets = (eb: ExpressionBuilder<DB, 'album'>) => {
return eb
.selectFrom((eb) =>
eb
.selectFrom('assets')
.selectAll('assets')
.leftJoin('exif', 'assets.id', 'exif.assetId')
.select((eb) => eb.table('exif').$castTo<Exif>().as('exifInfo'))
.innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id')
.whereRef('albums_assets_assets.albumsId', '=', 'albums.id')
.where('assets.deletedAt', 'is', null)
.selectFrom('asset')
.selectAll('asset')
.leftJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.select((eb) => eb.table('asset_exif').$castTo<Exif>().as('exifInfo'))
.innerJoin('album_asset', 'album_asset.assetsId', 'asset.id')
.whereRef('album_asset.albumsId', '=', 'album.id')
.where('asset.deletedAt', 'is', null)
.$call(withDefaultVisibility)
.orderBy('assets.fileCreatedAt', 'desc')
.orderBy('asset.fileCreatedAt', 'desc')
.as('asset'),
)
.select((eb) => eb.fn.jsonAgg('asset').as('assets'))
@ -75,10 +75,10 @@ export class AlbumRepository {
@GenerateSql({ params: [DummyValue.UUID, { withAssets: true }] })
async getById(id: string, options: AlbumInfoOptions) {
return this.db
.selectFrom('albums')
.selectAll('albums')
.where('albums.id', '=', id)
.where('albums.deletedAt', 'is', null)
.selectFrom('album')
.selectAll('album')
.where('album.id', '=', id)
.where('album.deletedAt', 'is', null)
.select(withOwner)
.select(withAlbumUsers)
.select(withSharedLink)
@ -90,26 +90,26 @@ export class AlbumRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
async getByAssetId(ownerId: string, assetId: string) {
return this.db
.selectFrom('albums')
.selectAll('albums')
.innerJoin('albums_assets_assets as album_assets', 'album_assets.albumsId', 'albums.id')
.selectFrom('album')
.selectAll('album')
.innerJoin('album_asset', 'album_asset.albumsId', 'album.id')
.where((eb) =>
eb.or([
eb('albums.ownerId', '=', ownerId),
eb('album.ownerId', '=', ownerId),
eb.exists(
eb
.selectFrom('albums_shared_users_users as album_users')
.whereRef('album_users.albumsId', '=', 'albums.id')
.where('album_users.usersId', '=', ownerId),
.selectFrom('album_user')
.whereRef('album_user.albumsId', '=', 'album.id')
.where('album_user.usersId', '=', ownerId),
),
]),
)
.where('album_assets.assetsId', '=', assetId)
.where('albums.deletedAt', 'is', null)
.orderBy('albums.createdAt', 'desc')
.where('album_asset.assetsId', '=', assetId)
.where('album.deletedAt', 'is', null)
.orderBy('album.createdAt', 'desc')
.select(withOwner)
.select(withAlbumUsers)
.orderBy('albums.createdAt', 'desc')
.orderBy('album.createdAt', 'desc')
.execute();
}
@ -123,18 +123,18 @@ export class AlbumRepository {
return (
this.db
.selectFrom('assets')
.selectFrom('asset')
.$call(withDefaultVisibility)
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'assets.id')
.select('album_assets.albumsId as albumId')
.select((eb) => eb.fn.min(sql<Date>`("assets"."localDateTime" AT TIME ZONE 'UTC'::text)::date`).as('startDate'))
.select((eb) => eb.fn.max(sql<Date>`("assets"."localDateTime" AT TIME ZONE 'UTC'::text)::date`).as('endDate'))
.innerJoin('album_asset', 'album_asset.assetsId', 'asset.id')
.select('album_asset.albumsId as albumId')
.select((eb) => eb.fn.min(sql<Date>`("asset"."localDateTime" AT TIME ZONE 'UTC'::text)::date`).as('startDate'))
.select((eb) => eb.fn.max(sql<Date>`("asset"."localDateTime" AT TIME ZONE 'UTC'::text)::date`).as('endDate'))
// lastModifiedAssetTimestamp is only used in mobile app, please remove if not need
.select((eb) => eb.fn.max('assets.updatedAt').as('lastModifiedAssetTimestamp'))
.select((eb) => sql<number>`${eb.fn.count('assets.id')}::int`.as('assetCount'))
.where('album_assets.albumsId', 'in', ids)
.where('assets.deletedAt', 'is', null)
.groupBy('album_assets.albumsId')
.select((eb) => eb.fn.max('asset.updatedAt').as('lastModifiedAssetTimestamp'))
.select((eb) => sql<number>`${eb.fn.count('asset.id')}::int`.as('assetCount'))
.where('album_asset.albumsId', 'in', ids)
.where('asset.deletedAt', 'is', null)
.groupBy('album_asset.albumsId')
.execute()
);
}
@ -142,14 +142,14 @@ export class AlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getOwned(ownerId: string) {
return this.db
.selectFrom('albums')
.selectAll('albums')
.selectFrom('album')
.selectAll('album')
.select(withOwner)
.select(withAlbumUsers)
.select(withSharedLink)
.where('albums.ownerId', '=', ownerId)
.where('albums.deletedAt', 'is', null)
.orderBy('albums.createdAt', 'desc')
.where('album.ownerId', '=', ownerId)
.where('album.deletedAt', 'is', null)
.orderBy('album.createdAt', 'desc')
.execute();
}
@ -159,29 +159,29 @@ export class AlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getShared(ownerId: string) {
return this.db
.selectFrom('albums')
.selectAll('albums')
.selectFrom('album')
.selectAll('album')
.where((eb) =>
eb.or([
eb.exists(
eb
.selectFrom('albums_shared_users_users as album_users')
.whereRef('album_users.albumsId', '=', 'albums.id')
.where((eb) => eb.or([eb('albums.ownerId', '=', ownerId), eb('album_users.usersId', '=', ownerId)])),
.selectFrom('album_user')
.whereRef('album_user.albumsId', '=', 'album.id')
.where((eb) => eb.or([eb('album.ownerId', '=', ownerId), eb('album_user.usersId', '=', ownerId)])),
),
eb.exists(
eb
.selectFrom('shared_links')
.whereRef('shared_links.albumId', '=', 'albums.id')
.where('shared_links.userId', '=', ownerId),
.selectFrom('shared_link')
.whereRef('shared_link.albumId', '=', 'album.id')
.where('shared_link.userId', '=', ownerId),
),
]),
)
.where('albums.deletedAt', 'is', null)
.where('album.deletedAt', 'is', null)
.select(withAlbumUsers)
.select(withOwner)
.select(withSharedLink)
.orderBy('albums.createdAt', 'desc')
.orderBy('album.createdAt', 'desc')
.execute();
}
@ -191,43 +191,33 @@ export class AlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getNotShared(ownerId: string) {
return this.db
.selectFrom('albums')
.selectAll('albums')
.where('albums.ownerId', '=', ownerId)
.where('albums.deletedAt', 'is', null)
.where((eb) =>
eb.not(
eb.exists(
eb
.selectFrom('albums_shared_users_users as album_users')
.whereRef('album_users.albumsId', '=', 'albums.id'),
),
),
)
.where((eb) =>
eb.not(eb.exists(eb.selectFrom('shared_links').whereRef('shared_links.albumId', '=', 'albums.id'))),
)
.selectFrom('album')
.selectAll('album')
.where('album.ownerId', '=', ownerId)
.where('album.deletedAt', 'is', null)
.where((eb) => eb.not(eb.exists(eb.selectFrom('album_user').whereRef('album_user.albumsId', '=', 'album.id'))))
.where((eb) => eb.not(eb.exists(eb.selectFrom('shared_link').whereRef('shared_link.albumId', '=', 'album.id'))))
.select(withOwner)
.orderBy('albums.createdAt', 'desc')
.orderBy('album.createdAt', 'desc')
.execute();
}
async restoreAll(userId: string): Promise<void> {
await this.db.updateTable('albums').set({ deletedAt: null }).where('ownerId', '=', userId).execute();
await this.db.updateTable('album').set({ deletedAt: null }).where('ownerId', '=', userId).execute();
}
async softDeleteAll(userId: string): Promise<void> {
await this.db.updateTable('albums').set({ deletedAt: new Date() }).where('ownerId', '=', userId).execute();
await this.db.updateTable('album').set({ deletedAt: new Date() }).where('ownerId', '=', userId).execute();
}
async deleteAll(userId: string): Promise<void> {
await this.db.deleteFrom('albums').where('ownerId', '=', userId).execute();
await this.db.deleteFrom('album').where('ownerId', '=', userId).execute();
}
@GenerateSql({ params: [[DummyValue.UUID]] })
@Chunked()
async removeAssetsFromAll(assetIds: string[]): Promise<void> {
await this.db.deleteFrom('albums_assets_assets').where('albums_assets_assets.assetsId', 'in', assetIds).execute();
await this.db.deleteFrom('album_asset').where('album_asset.assetsId', 'in', assetIds).execute();
}
@Chunked({ paramIndex: 1 })
@ -237,9 +227,9 @@ export class AlbumRepository {
}
await this.db
.deleteFrom('albums_assets_assets')
.where('albums_assets_assets.albumsId', '=', albumId)
.where('albums_assets_assets.assetsId', 'in', assetIds)
.deleteFrom('album_asset')
.where('album_asset.albumsId', '=', albumId)
.where('album_asset.assetsId', 'in', assetIds)
.execute();
}
@ -258,10 +248,10 @@ export class AlbumRepository {
}
return this.db
.selectFrom('albums_assets_assets')
.selectFrom('album_asset')
.selectAll()
.where('albums_assets_assets.albumsId', '=', albumId)
.where('albums_assets_assets.assetsId', 'in', assetIds)
.where('album_asset.albumsId', '=', albumId)
.where('album_asset.assetsId', 'in', assetIds)
.execute()
.then((results) => new Set(results.map(({ assetsId }) => assetsId)));
}
@ -272,7 +262,7 @@ export class AlbumRepository {
create(album: Insertable<AlbumTable>, assetIds: string[], albumUsers: AlbumUserCreateDto[]) {
return this.db.transaction().execute(async (tx) => {
const newAlbum = await tx.insertInto('albums').values(album).returning('albums.id').executeTakeFirst();
const newAlbum = await tx.insertInto('album').values(album).returning('album.id').executeTakeFirst();
if (!newAlbum) {
throw new Error('Failed to create album');
@ -284,7 +274,7 @@ export class AlbumRepository {
if (albumUsers.length > 0) {
await tx
.insertInto('albums_shared_users_users')
.insertInto('album_user')
.values(
albumUsers.map((albumUser) => ({ albumsId: newAlbum.id, usersId: albumUser.userId, role: albumUser.role })),
)
@ -292,7 +282,7 @@ export class AlbumRepository {
}
return tx
.selectFrom('albums')
.selectFrom('album')
.selectAll()
.where('id', '=', newAlbum.id)
.select(withOwner)
@ -305,10 +295,10 @@ export class AlbumRepository {
update(id: string, album: Updateable<AlbumTable>) {
return this.db
.updateTable('albums')
.updateTable('album')
.set(album)
.where('id', '=', id)
.returningAll('albums')
.returningAll('album')
.returning(withOwner)
.returning(withSharedLink)
.returning(withAlbumUsers)
@ -316,7 +306,7 @@ export class AlbumRepository {
}
async delete(id: string): Promise<void> {
await this.db.deleteFrom('albums').where('id', '=', id).execute();
await this.db.deleteFrom('album').where('id', '=', id).execute();
}
@Chunked({ paramIndex: 2, chunkSize: 30_000 })
@ -326,7 +316,7 @@ export class AlbumRepository {
}
await db
.insertInto('albums_assets_assets')
.insertInto('album_asset')
.values(assetIds.map((assetId) => ({ albumsId: albumId, assetsId: assetId })))
.execute();
}
@ -343,11 +333,11 @@ export class AlbumRepository {
// Subquery for getting a new thumbnail.
const result = await this.db
.updateTable('albums')
.updateTable('album')
.set((eb) => ({
albumThumbnailAssetId: this.updateThumbnailBuilder(eb)
.select('album_assets.assetsId')
.orderBy('assets.fileCreatedAt', 'desc')
.select('album_asset.assetsId')
.orderBy('asset.fileCreatedAt', 'desc')
.limit(1),
}))
.where((eb) =>
@ -362,7 +352,7 @@ export class AlbumRepository {
eb.exists(
this.updateThumbnailBuilder(eb)
.select(sql`1`.as('1'))
.whereRef('albums.albumThumbnailAssetId', '=', 'album_assets.assetsId'), // Has invalid assets
.whereRef('album.albumThumbnailAssetId', '=', 'album_asset.assetsId'), // Has invalid assets
),
),
]),
@ -373,12 +363,12 @@ export class AlbumRepository {
return Number(result[0].numUpdatedRows);
}
private updateThumbnailBuilder(eb: ExpressionBuilder<DB, 'albums'>) {
private updateThumbnailBuilder(eb: ExpressionBuilder<DB, 'album'>) {
return eb
.selectFrom('albums_assets_assets as album_assets')
.innerJoin('assets', (join) =>
join.onRef('album_assets.assetsId', '=', 'assets.id').on('assets.deletedAt', 'is', null),
.selectFrom('album_asset')
.innerJoin('asset', (join) =>
join.onRef('album_asset.assetsId', '=', 'asset.id').on('asset.deletedAt', 'is', null),
)
.whereRef('album_assets.albumsId', '=', 'albums.id');
.whereRef('album_asset.albumsId', '=', 'album.id');
}
}

View File

@ -13,45 +13,45 @@ export class ApiKeyRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}
create(dto: Insertable<ApiKeyTable>) {
return this.db.insertInto('api_keys').values(dto).returning(columns.apiKey).executeTakeFirstOrThrow();
return this.db.insertInto('api_key').values(dto).returning(columns.apiKey).executeTakeFirstOrThrow();
}
async update(userId: string, id: string, dto: Updateable<ApiKeyTable>) {
return this.db
.updateTable('api_keys')
.updateTable('api_key')
.set(dto)
.where('api_keys.userId', '=', userId)
.where('api_key.userId', '=', userId)
.where('id', '=', asUuid(id))
.returning(columns.apiKey)
.executeTakeFirstOrThrow();
}
async delete(userId: string, id: string) {
await this.db.deleteFrom('api_keys').where('userId', '=', userId).where('id', '=', asUuid(id)).execute();
await this.db.deleteFrom('api_key').where('userId', '=', userId).where('id', '=', asUuid(id)).execute();
}
@GenerateSql({ params: [DummyValue.STRING] })
getKey(hashedToken: string) {
return this.db
.selectFrom('api_keys')
.selectFrom('api_key')
.select((eb) => [
...columns.authApiKey,
jsonObjectFrom(
eb
.selectFrom('users')
.selectFrom('user')
.select(columns.authUser)
.whereRef('users.id', '=', 'api_keys.userId')
.where('users.deletedAt', 'is', null),
.whereRef('user.id', '=', 'api_key.userId')
.where('user.deletedAt', 'is', null),
).as('user'),
])
.where('api_keys.key', '=', hashedToken)
.where('api_key.key', '=', hashedToken)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
getById(userId: string, id: string) {
return this.db
.selectFrom('api_keys')
.selectFrom('api_key')
.select(columns.apiKey)
.where('id', '=', asUuid(id))
.where('userId', '=', userId)
@ -61,7 +61,7 @@ export class ApiKeyRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getByUserId(userId: string) {
return this.db
.selectFrom('api_keys')
.selectFrom('api_key')
.select(columns.apiKey)
.where('userId', '=', userId)
.orderBy('createdAt', 'desc')

View File

@ -26,9 +26,9 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForSearchDuplicatesJob(id: string) {
return this.db
.selectFrom('assets')
.where('assets.id', '=', asUuid(id))
.leftJoin('smart_search', 'assets.id', 'smart_search.assetId')
.selectFrom('asset')
.where('asset.id', '=', asUuid(id))
.leftJoin('smart_search', 'asset.id', 'smart_search.assetId')
.select(['id', 'type', 'ownerId', 'duplicateId', 'stackId', 'visibility', 'smart_search.embedding'])
.limit(1)
.executeTakeFirst();
@ -37,18 +37,18 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForSidecarWriteJob(id: string) {
return this.db
.selectFrom('assets')
.where('assets.id', '=', asUuid(id))
.selectFrom('asset')
.where('asset.id', '=', asUuid(id))
.select((eb) => [
'id',
'sidecarPath',
'originalPath',
jsonArrayFrom(
eb
.selectFrom('tags')
.select(['tags.value'])
.innerJoin('tag_asset', 'tags.id', 'tag_asset.tagsId')
.whereRef('assets.id', '=', 'tag_asset.assetsId'),
.selectFrom('tag')
.select(['tag.value'])
.innerJoin('tag_asset', 'tag.id', 'tag_asset.tagsId')
.whereRef('asset.id', '=', 'tag_asset.assetsId'),
).as('tags'),
])
.limit(1)
@ -58,20 +58,20 @@ export class AssetJobRepository {
@GenerateSql({ params: [false], stream: true })
streamForThumbnailJob(force: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.thumbhash'])
.selectFrom('asset')
.select(['asset.id', 'asset.thumbhash'])
.select(withFiles)
.where('assets.deletedAt', 'is', null)
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.deletedAt', 'is', null)
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.$if(!force, (qb) =>
qb
// If there aren't any entries, metadata extraction hasn't run yet which is required for thumbnails
.innerJoin('asset_job_status', 'asset_job_status.assetId', 'assets.id')
.innerJoin('asset_job_status', 'asset_job_status.assetId', 'asset.id')
.where((eb) =>
eb.or([
eb('asset_job_status.previewAt', 'is', null),
eb('asset_job_status.thumbnailAt', 'is', null),
eb('assets.thumbhash', 'is', null),
eb('asset.thumbhash', 'is', null),
]),
),
)
@ -81,72 +81,72 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForMigrationJob(id: string) {
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.ownerId', 'assets.encodedVideoPath'])
.selectFrom('asset')
.select(['asset.id', 'asset.ownerId', 'asset.encodedVideoPath'])
.select(withFiles)
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForGenerateThumbnailJob(id: string) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select([
'assets.id',
'assets.visibility',
'assets.originalFileName',
'assets.originalPath',
'assets.ownerId',
'assets.thumbhash',
'assets.type',
'asset.id',
'asset.visibility',
'asset.originalFileName',
'asset.originalPath',
'asset.ownerId',
'asset.thumbhash',
'asset.type',
])
.select(withFiles)
.$call(withExifInner)
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForMetadataExtraction(id: string) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(columns.asset)
.select(withFaces)
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID, AssetFileType.THUMBNAIL] })
getAlbumThumbnailFiles(id: string, fileType?: AssetFileType) {
return this.db
.selectFrom('asset_files')
.selectFrom('asset_file')
.select(columns.assetFiles)
.where('asset_files.assetId', '=', id)
.$if(!!fileType, (qb) => qb.where('asset_files.type', '=', fileType!))
.where('asset_file.assetId', '=', id)
.$if(!!fileType, (qb) => qb.where('asset_file.type', '=', fileType!))
.execute();
}
private assetsWithPreviews() {
return this.db
.selectFrom('assets')
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('assets.deletedAt', 'is', null)
.innerJoin('asset_job_status as job_status', 'assetId', 'assets.id')
.selectFrom('asset')
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.deletedAt', 'is', null)
.innerJoin('asset_job_status as job_status', 'assetId', 'asset.id')
.where('job_status.previewAt', 'is not', null);
}
@GenerateSql({ params: [], stream: true })
streamForSearchDuplicates(force?: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id'])
.where('assets.deletedAt', 'is', null)
.innerJoin('smart_search', 'assets.id', 'smart_search.assetId')
.selectFrom('asset')
.select(['asset.id'])
.where('asset.deletedAt', 'is', null)
.innerJoin('smart_search', 'asset.id', 'smart_search.assetId')
.$call(withDefaultVisibility)
.$if(!force, (qb) =>
qb
.innerJoin('asset_job_status as job_status', 'job_status.assetId', 'assets.id')
.innerJoin('asset_job_status as job_status', 'job_status.assetId', 'asset.id')
.where('job_status.duplicatesDetectedAt', 'is', null),
)
.stream();
@ -155,11 +155,9 @@ export class AssetJobRepository {
@GenerateSql({ params: [], stream: true })
streamForEncodeClip(force?: boolean) {
return this.assetsWithPreviews()
.select(['assets.id'])
.select(['asset.id'])
.$if(!force, (qb) =>
qb.where((eb) =>
eb.not((eb) => eb.exists(eb.selectFrom('smart_search').whereRef('assetId', '=', 'assets.id'))),
),
qb.where((eb) => eb.not((eb) => eb.exists(eb.selectFrom('smart_search').whereRef('assetId', '=', 'asset.id')))),
)
.stream();
}
@ -167,142 +165,142 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForClipEncoding(id: string) {
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.visibility'])
.selectFrom('asset')
.select(['asset.id', 'asset.visibility'])
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForDetectFacesJob(id: string) {
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.visibility'])
.selectFrom('asset')
.select(['asset.id', 'asset.visibility'])
.$call(withExifInner)
.select((eb) => withFaces(eb, true))
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [[DummyValue.UUID]] })
getForSyncAssets(ids: string[]) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select([
'assets.id',
'assets.isOffline',
'assets.libraryId',
'assets.originalPath',
'assets.status',
'assets.fileModifiedAt',
'asset.id',
'asset.isOffline',
'asset.libraryId',
'asset.originalPath',
'asset.status',
'asset.fileModifiedAt',
])
.where('assets.id', '=', anyUuid(ids))
.where('asset.id', '=', anyUuid(ids))
.execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForAssetDeletion(id: string) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select([
'assets.id',
'assets.visibility',
'assets.libraryId',
'assets.ownerId',
'assets.livePhotoVideoId',
'assets.sidecarPath',
'assets.encodedVideoPath',
'assets.originalPath',
'asset.id',
'asset.visibility',
'asset.libraryId',
'asset.ownerId',
'asset.livePhotoVideoId',
'asset.sidecarPath',
'asset.encodedVideoPath',
'asset.originalPath',
])
.$call(withExif)
.select(withFacesAndPeople)
.select(withFiles)
.leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId')
.leftJoin('stack', 'stack.id', 'asset.stackId')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets as stacked')
.select(['asset_stack.id', 'asset_stack.primaryAssetId'])
.selectFrom('asset as stacked')
.select(['stack.id', 'stack.primaryAssetId'])
.select((eb) => eb.fn<Asset[]>('array_agg', [eb.table('stacked')]).as('assets'))
.where('stacked.deletedAt', 'is not', null)
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
.whereRef('stacked.stackId', '=', 'asset_stack.id')
.groupBy('asset_stack.id')
.whereRef('stacked.stackId', '=', 'stack.id')
.groupBy('stack.id')
.as('stacked_assets'),
(join) => join.on('asset_stack.id', 'is not', null),
(join) => join.on('stack.id', 'is not', null),
)
.select((eb) => toJson(eb, 'stacked_assets').as('stack'))
.where('assets.id', '=', id)
.where('asset.id', '=', id)
.executeTakeFirst();
}
@GenerateSql({ params: [], stream: true })
streamForVideoConversion(force?: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id'])
.where('assets.type', '=', AssetType.VIDEO)
.selectFrom('asset')
.select(['asset.id'])
.where('asset.type', '=', AssetType.VIDEO)
.$if(!force, (qb) =>
qb
.where((eb) => eb.or([eb('assets.encodedVideoPath', 'is', null), eb('assets.encodedVideoPath', '=', '')]))
.where('assets.visibility', '!=', AssetVisibility.HIDDEN),
.where((eb) => eb.or([eb('asset.encodedVideoPath', 'is', null), eb('asset.encodedVideoPath', '=', '')]))
.where('asset.visibility', '!=', AssetVisibility.HIDDEN),
)
.where('assets.deletedAt', 'is', null)
.where('asset.deletedAt', 'is', null)
.stream();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForVideoConversion(id: string) {
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.ownerId', 'assets.originalPath', 'assets.encodedVideoPath'])
.where('assets.id', '=', id)
.where('assets.type', '=', AssetType.VIDEO)
.selectFrom('asset')
.select(['asset.id', 'asset.ownerId', 'asset.originalPath', 'asset.encodedVideoPath'])
.where('asset.id', '=', id)
.where('asset.type', '=', AssetType.VIDEO)
.executeTakeFirst();
}
@GenerateSql({ params: [], stream: true })
streamForMetadataExtraction(force?: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id'])
.selectFrom('asset')
.select(['asset.id'])
.$if(!force, (qb) =>
qb
.leftJoin('asset_job_status', 'asset_job_status.assetId', 'assets.id')
.leftJoin('asset_job_status', 'asset_job_status.assetId', 'asset.id')
.where((eb) =>
eb.or([eb('asset_job_status.metadataExtractedAt', 'is', null), eb('asset_job_status.assetId', 'is', null)]),
),
)
.where('assets.deletedAt', 'is', null)
.where('asset.deletedAt', 'is', null)
.stream();
}
private storageTemplateAssetQuery() {
return this.db
.selectFrom('assets')
.innerJoin('exif', 'assets.id', 'exif.assetId')
.selectFrom('asset')
.innerJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.select([
'assets.id',
'assets.ownerId',
'assets.type',
'assets.checksum',
'assets.originalPath',
'assets.isExternal',
'assets.sidecarPath',
'assets.originalFileName',
'assets.livePhotoVideoId',
'assets.fileCreatedAt',
'exif.timeZone',
'exif.fileSizeInByte',
'asset.id',
'asset.ownerId',
'asset.type',
'asset.checksum',
'asset.originalPath',
'asset.isExternal',
'asset.sidecarPath',
'asset.originalFileName',
'asset.livePhotoVideoId',
'asset.fileCreatedAt',
'asset_exif.timeZone',
'asset_exif.fileSizeInByte',
])
.where('assets.deletedAt', 'is', null);
.where('asset.deletedAt', 'is', null);
}
@GenerateSql({ params: [DummyValue.UUID] })
getForStorageTemplateJob(id: string): Promise<StorageAsset | undefined> {
return this.storageTemplateAssetQuery().where('assets.id', '=', id).executeTakeFirst() as Promise<
return this.storageTemplateAssetQuery().where('asset.id', '=', id).executeTakeFirst() as Promise<
StorageAsset | undefined
>;
}
@ -315,21 +313,21 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.DATE], stream: true })
streamForDeletedJob(trashedBefore: Date) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(['id', 'isOffline'])
.where('assets.deletedAt', '<=', trashedBefore)
.where('asset.deletedAt', '<=', trashedBefore)
.stream();
}
@GenerateSql({ params: [], stream: true })
streamForSidecar(force?: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id'])
.selectFrom('asset')
.select(['asset.id'])
.$if(!force, (qb) =>
qb.where((eb) => eb.or([eb('assets.sidecarPath', '=', ''), eb('assets.sidecarPath', 'is', null)])),
qb.where((eb) => eb.or([eb('asset.sidecarPath', '=', ''), eb('asset.sidecarPath', 'is', null)])),
)
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.stream();
}
@ -337,13 +335,13 @@ export class AssetJobRepository {
streamForDetectFacesJob(force?: boolean) {
return this.assetsWithPreviews()
.$if(!force, (qb) => qb.where('job_status.facesRecognizedAt', 'is', null))
.select(['assets.id'])
.orderBy('assets.createdAt', 'desc')
.select(['asset.id'])
.orderBy('asset.createdAt', 'desc')
.stream();
}
@GenerateSql({ params: [DummyValue.DATE], stream: true })
streamForMigrationJob() {
return this.db.selectFrom('assets').select(['id']).where('assets.deletedAt', 'is', null).stream();
return this.db.selectFrom('asset').select(['id']).where('asset.deletedAt', 'is', null).stream();
}
}

View File

@ -6,10 +6,10 @@ import { Stack } from 'src/database';
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
import { AssetFileType, AssetOrder, AssetStatus, AssetType, AssetVisibility } from 'src/enum';
import { DB } from 'src/schema';
import { AssetFileTable } from 'src/schema/tables/asset-files.table';
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { AssetFileTable } from 'src/schema/tables/asset-file.table';
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
import { AssetTable } from 'src/schema/tables/asset.table';
import { ExifTable } from 'src/schema/tables/exif.table';
import {
anyUuid,
asUuid,
@ -114,10 +114,10 @@ interface GetByIdsRelations {
export class AssetRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}
async upsertExif(exif: Insertable<ExifTable>): Promise<void> {
async upsertExif(exif: Insertable<AssetExifTable>): Promise<void> {
const value = { ...exif, assetId: asUuid(exif.assetId) };
await this.db
.insertInto('exif')
.insertInto('asset_exif')
.values(value)
.onConflict((oc) =>
oc.column('assetId').doUpdateSet((eb) =>
@ -161,12 +161,12 @@ export class AssetRepository {
@GenerateSql({ params: [[DummyValue.UUID], { model: DummyValue.STRING }] })
@Chunked()
async updateAllExif(ids: string[], options: Updateable<ExifTable>): Promise<void> {
async updateAllExif(ids: string[], options: Updateable<AssetExifTable>): Promise<void> {
if (ids.length === 0) {
return;
}
await this.db.updateTable('exif').set(options).where('assetId', 'in', ids).execute();
await this.db.updateTable('asset_exif').set(options).where('assetId', 'in', ids).execute();
}
async upsertJobStatus(...jobStatus: Insertable<AssetJobStatusTable>[]): Promise<void> {
@ -196,11 +196,11 @@ export class AssetRepository {
}
create(asset: Insertable<AssetTable>) {
return this.db.insertInto('assets').values(asset).returningAll().executeTakeFirstOrThrow();
return this.db.insertInto('asset').values(asset).returningAll().executeTakeFirstOrThrow();
}
createAll(assets: Insertable<AssetTable>[]) {
return this.db.insertInto('assets').values(assets).returningAll().execute();
return this.db.insertInto('asset').values(assets).returningAll().execute();
}
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
@ -213,7 +213,7 @@ export class AssetRepository {
.selectFrom((eb) =>
eb
.fn('generate_series', [
sql`(select date_part('year', min(("localDateTime" at time zone 'UTC')::date))::int from assets)`,
sql`(select date_part('year', min(("localDateTime" at time zone 'UTC')::date))::int from asset)`,
sql`date_part('year', current_date)::int - 1`,
])
.as('year'),
@ -224,30 +224,30 @@ export class AssetRepository {
.innerJoinLateral(
(qb) =>
qb
.selectFrom('assets')
.selectAll('assets')
.innerJoin('asset_job_status', 'assets.id', 'asset_job_status.assetId')
.selectFrom('asset')
.selectAll('asset')
.innerJoin('asset_job_status', 'asset.id', 'asset_job_status.assetId')
.where('asset_job_status.previewAt', 'is not', null)
.where(sql`(assets."localDateTime" at time zone 'UTC')::date`, '=', sql`today.date`)
.where('assets.ownerId', '=', anyUuid(ownerIds))
.where('assets.visibility', '=', AssetVisibility.TIMELINE)
.where(sql`(asset."localDateTime" at time zone 'UTC')::date`, '=', sql`today.date`)
.where('asset.ownerId', '=', anyUuid(ownerIds))
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
.where((eb) =>
eb.exists((qb) =>
qb
.selectFrom('asset_files')
.whereRef('assetId', '=', 'assets.id')
.where('asset_files.type', '=', AssetFileType.PREVIEW),
.selectFrom('asset_file')
.whereRef('assetId', '=', 'asset.id')
.where('asset_file.type', '=', AssetFileType.PREVIEW),
),
)
.where('assets.deletedAt', 'is', null)
.orderBy(sql`(assets."localDateTime" at time zone 'UTC')::date`, 'desc')
.where('asset.deletedAt', 'is', null)
.orderBy(sql`(asset."localDateTime" at time zone 'UTC')::date`, 'desc')
.limit(20)
.as('a'),
(join) => join.onTrue(),
)
.innerJoin('exif', 'a.id', 'exif.assetId')
.innerJoin('asset_exif', 'a.id', 'asset_exif.assetId')
.selectAll('a')
.select((eb) => eb.fn.toJson(eb.table('exif')).as('exifInfo')),
.select((eb) => eb.fn.toJson(eb.table('asset_exif')).as('exifInfo')),
)
.selectFrom('res')
.select(sql<number>`date_part('year', ("localDateTime" at time zone 'UTC')::date)::int`.as('year'))
@ -260,30 +260,30 @@ export class AssetRepository {
@GenerateSql({ params: [[DummyValue.UUID]] })
@ChunkedArray()
getByIds(ids: string[]) {
return this.db.selectFrom('assets').selectAll('assets').where('assets.id', '=', anyUuid(ids)).execute();
return this.db.selectFrom('asset').selectAll('asset').where('asset.id', '=', anyUuid(ids)).execute();
}
@GenerateSql({ params: [[DummyValue.UUID]] })
@ChunkedArray()
getByIdsWithAllRelationsButStacks(ids: string[]) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.select(withFacesAndPeople)
.select(withTags)
.$call(withExif)
.where('assets.id', '=', anyUuid(ids))
.where('asset.id', '=', anyUuid(ids))
.execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async deleteAll(ownerId: string): Promise<void> {
await this.db.deleteFrom('assets').where('ownerId', '=', ownerId).execute();
await this.db.deleteFrom('asset').where('ownerId', '=', ownerId).execute();
}
async getByDeviceIds(ownerId: string, deviceId: string, deviceAssetIds: string[]): Promise<string[]> {
const assets = await this.db
.selectFrom('assets')
.selectFrom('asset')
.select(['deviceAssetId'])
.where('deviceAssetId', 'in', deviceAssetIds)
.where('deviceId', '=', deviceId)
@ -296,8 +296,8 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.where('libraryId', '=', asUuid(libraryId))
.where('originalPath', '=', originalPath)
.limit(1)
@ -314,7 +314,7 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
async getAllByDeviceId(ownerId: string, deviceId: string): Promise<string[]> {
const items = await this.db
.selectFrom('assets')
.selectFrom('asset')
.select(['deviceAssetId'])
.where('ownerId', '=', asUuid(ownerId))
.where('deviceId', '=', deviceId)
@ -328,7 +328,7 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getLivePhotoCount(motionId: string): Promise<number> {
const [{ count }] = await this.db
.selectFrom('assets')
.selectFrom('asset')
.select((eb) => eb.fn.countAll<number>().as('count'))
.where('livePhotoVideoId', '=', asUuid(motionId))
.execute();
@ -338,9 +338,9 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getById(id: string, { exifInfo, faces, files, library, owner, smartSearch, stack, tags }: GetByIdsRelations = {}) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.where('assets.id', '=', asUuid(id))
.selectFrom('asset')
.selectAll('asset')
.where('asset.id', '=', asUuid(id))
.$if(!!exifInfo, withExif)
.$if(!!faces, (qb) => qb.select(faces?.person ? withFacesAndPeople : withFaces).$narrowType<{ faces: NotNull }>())
.$if(!!library, (qb) => qb.select(withLibrary))
@ -348,25 +348,25 @@ export class AssetRepository {
.$if(!!smartSearch, withSmartSearch)
.$if(!!stack, (qb) =>
qb
.leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId')
.leftJoin('stack', 'stack.id', 'asset.stackId')
.$if(!stack!.assets, (qb) =>
qb.select((eb) => eb.fn.toJson(eb.table('asset_stack')).$castTo<Stack | null>().as('stack')),
qb.select((eb) => eb.fn.toJson(eb.table('stack')).$castTo<Stack | null>().as('stack')),
)
.$if(!!stack!.assets, (qb) =>
qb
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets as stacked')
.selectAll('asset_stack')
.selectFrom('asset as stacked')
.selectAll('stack')
.select((eb) => eb.fn('array_agg', [eb.table('stacked')]).as('assets'))
.whereRef('stacked.stackId', '=', 'asset_stack.id')
.whereRef('stacked.id', '!=', 'asset_stack.primaryAssetId')
.whereRef('stacked.stackId', '=', 'stack.id')
.whereRef('stacked.id', '!=', 'stack.primaryAssetId')
.where('stacked.deletedAt', 'is', null)
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
.groupBy('asset_stack.id')
.groupBy('stack.id')
.as('stacked_assets'),
(join) => join.on('asset_stack.id', 'is not', null),
(join) => join.on('stack.id', 'is not', null),
)
.select((eb) => eb.fn.toJson(eb.table('stacked_assets')).$castTo<Stack | null>().as('stack')),
),
@ -383,11 +383,11 @@ export class AssetRepository {
if (ids.length === 0) {
return;
}
await this.db.updateTable('assets').set(options).where('id', '=', anyUuid(ids)).execute();
await this.db.updateTable('asset').set(options).where('id', '=', anyUuid(ids)).execute();
}
async updateByLibraryId(libraryId: string, options: Updateable<AssetTable>): Promise<void> {
await this.db.updateTable('assets').set(options).where('libraryId', '=', asUuid(libraryId)).execute();
await this.db.updateTable('asset').set(options).where('libraryId', '=', asUuid(libraryId)).execute();
}
async update(asset: Updateable<AssetTable> & { id: string }) {
@ -395,9 +395,9 @@ export class AssetRepository {
delete value.id;
if (!isEmpty(value)) {
return this.db
.with('assets', (qb) => qb.updateTable('assets').set(asset).where('id', '=', asUuid(asset.id)).returningAll())
.selectFrom('assets')
.selectAll('assets')
.with('asset', (qb) => qb.updateTable('asset').set(asset).where('id', '=', asUuid(asset.id)).returningAll())
.selectFrom('asset')
.selectAll('asset')
.$call(withExif)
.$call((qb) => qb.select(withFacesAndPeople))
.executeTakeFirst();
@ -407,14 +407,14 @@ export class AssetRepository {
}
async remove(asset: { id: string }): Promise<void> {
await this.db.deleteFrom('assets').where('id', '=', asUuid(asset.id)).execute();
await this.db.deleteFrom('asset').where('id', '=', asUuid(asset.id)).execute();
}
@GenerateSql({ params: [{ ownerId: DummyValue.UUID, libraryId: DummyValue.UUID, checksum: DummyValue.BUFFER }] })
getByChecksum({ ownerId, libraryId, checksum }: AssetGetByChecksumOptions) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.where('ownerId', '=', asUuid(ownerId))
.where('checksum', '=', checksum)
.$call((qb) => (libraryId ? qb.where('libraryId', '=', asUuid(libraryId)) : qb.where('libraryId', 'is', null)))
@ -425,7 +425,7 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.BUFFER]] })
getByChecksums(userId: string, checksums: Buffer[]) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(['id', 'checksum', 'deletedAt'])
.where('ownerId', '=', asUuid(userId))
.where('checksum', 'in', checksums)
@ -435,7 +435,7 @@ export class AssetRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.BUFFER] })
async getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined> {
const asset = await this.db
.selectFrom('assets')
.selectFrom('asset')
.select('id')
.where('ownerId', '=', asUuid(ownerId))
.where('checksum', '=', checksum)
@ -449,37 +449,37 @@ export class AssetRepository {
findLivePhotoMatch(options: LivePhotoSearchOptions) {
const { ownerId, otherAssetId, livePhotoCID, type } = options;
return this.db
.selectFrom('assets')
.select(['assets.id', 'assets.ownerId'])
.innerJoin('exif', 'assets.id', 'exif.assetId')
.selectFrom('asset')
.select(['asset.id', 'asset.ownerId'])
.innerJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.where('id', '!=', asUuid(otherAssetId))
.where('ownerId', '=', asUuid(ownerId))
.where('type', '=', type)
.where('exif.livePhotoCID', '=', livePhotoCID)
.where('asset_exif.livePhotoCID', '=', livePhotoCID)
.limit(1)
.executeTakeFirst();
}
getStatistics(ownerId: string, { visibility, isFavorite, isTrashed }: AssetStatsOptions): Promise<AssetStats> {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.AUDIO).as(AssetType.AUDIO))
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.IMAGE).as(AssetType.IMAGE))
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.VIDEO).as(AssetType.VIDEO))
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.OTHER).as(AssetType.OTHER))
.where('ownerId', '=', asUuid(ownerId))
.$if(visibility === undefined, withDefaultVisibility)
.$if(!!visibility, (qb) => qb.where('assets.visibility', '=', visibility!))
.$if(!!visibility, (qb) => qb.where('asset.visibility', '=', visibility!))
.$if(isFavorite !== undefined, (qb) => qb.where('isFavorite', '=', isFavorite!))
.$if(!!isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
.$if(!!isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
.where('deletedAt', isTrashed ? 'is not' : 'is', null)
.executeTakeFirstOrThrow();
}
getRandom(userIds: string[], take: number) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.$call(withExif)
.$call(withDefaultVisibility)
.where('ownerId', '=', anyUuid(userIds))
@ -492,38 +492,36 @@ export class AssetRepository {
@GenerateSql({ params: [{}] })
async getTimeBuckets(options: TimeBucketOptions): Promise<TimeBucketItem[]> {
return this.db
.with('assets', (qb) =>
.with('asset', (qb) =>
qb
.selectFrom('assets')
.selectFrom('asset')
.select(truncatedDate<Date>().as('timeBucket'))
.$if(!!options.isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
.where('assets.deletedAt', options.isTrashed ? 'is not' : 'is', null)
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
.where('asset.deletedAt', options.isTrashed ? 'is not' : 'is', null)
.$if(options.visibility === undefined, withDefaultVisibility)
.$if(!!options.visibility, (qb) => qb.where('assets.visibility', '=', options.visibility!))
.$if(!!options.visibility, (qb) => qb.where('asset.visibility', '=', options.visibility!))
.$if(!!options.albumId, (qb) =>
qb
.innerJoin('albums_assets_assets', 'assets.id', 'albums_assets_assets.assetsId')
.where('albums_assets_assets.albumsId', '=', asUuid(options.albumId!)),
.innerJoin('album_asset', 'asset.id', 'album_asset.assetsId')
.where('album_asset.albumsId', '=', asUuid(options.albumId!)),
)
.$if(!!options.personId, (qb) => hasPeople(qb, [options.personId!]))
.$if(!!options.withStacked, (qb) =>
qb
.leftJoin('asset_stack', (join) =>
join
.onRef('asset_stack.id', '=', 'assets.stackId')
.onRef('asset_stack.primaryAssetId', '=', 'assets.id'),
.leftJoin('stack', (join) =>
join.onRef('stack.id', '=', 'asset.stackId').onRef('stack.primaryAssetId', '=', 'asset.id'),
)
.where((eb) => eb.or([eb('assets.stackId', 'is', null), eb(eb.table('asset_stack'), 'is not', null)])),
.where((eb) => eb.or([eb('asset.stackId', 'is', null), eb(eb.table('stack'), 'is not', null)])),
)
.$if(!!options.userIds, (qb) => qb.where('assets.ownerId', '=', anyUuid(options.userIds!)))
.$if(options.isFavorite !== undefined, (qb) => qb.where('assets.isFavorite', '=', options.isFavorite!))
.$if(!!options.assetType, (qb) => qb.where('assets.type', '=', options.assetType!))
.$if(!!options.userIds, (qb) => qb.where('asset.ownerId', '=', anyUuid(options.userIds!)))
.$if(options.isFavorite !== undefined, (qb) => qb.where('asset.isFavorite', '=', options.isFavorite!))
.$if(!!options.assetType, (qb) => qb.where('asset.type', '=', options.assetType!))
.$if(options.isDuplicate !== undefined, (qb) =>
qb.where('assets.duplicateId', options.isDuplicate ? 'is not' : 'is', null),
qb.where('asset.duplicateId', options.isDuplicate ? 'is not' : 'is', null),
)
.$if(!!options.tagId, (qb) => withTagId(qb, options.tagId!)),
)
.selectFrom('assets')
.selectFrom('asset')
.select(sql<string>`("timeBucket" AT TIME ZONE 'UTC')::date::text`.as('timeBucket'))
.select((eb) => eb.fn.countAll<number>().as('count'))
.groupBy('timeBucket')
@ -538,75 +536,75 @@ export class AssetRepository {
const query = this.db
.with('cte', (qb) =>
qb
.selectFrom('assets')
.innerJoin('exif', 'assets.id', 'exif.assetId')
.selectFrom('asset')
.innerJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.select((eb) => [
'assets.duration',
'assets.id',
'assets.visibility',
'assets.isFavorite',
sql`assets.type = 'IMAGE'`.as('isImage'),
sql`assets."deletedAt" is not null`.as('isTrashed'),
'assets.livePhotoVideoId',
sql`extract(epoch from (assets."localDateTime" - assets."fileCreatedAt" at time zone 'UTC'))::real / 3600`.as(
'asset.duration',
'asset.id',
'asset.visibility',
'asset.isFavorite',
sql`asset.type = 'IMAGE'`.as('isImage'),
sql`asset."deletedAt" is not null`.as('isTrashed'),
'asset.livePhotoVideoId',
sql`extract(epoch from (asset."localDateTime" - asset."fileCreatedAt" at time zone 'UTC'))::real / 3600`.as(
'localOffsetHours',
),
'assets.ownerId',
'assets.status',
sql`assets."fileCreatedAt" at time zone 'utc'`.as('fileCreatedAt'),
eb.fn('encode', ['assets.thumbhash', sql.lit('base64')]).as('thumbhash'),
'exif.city',
'exif.country',
'exif.projectionType',
'asset.ownerId',
'asset.status',
sql`asset."fileCreatedAt" at time zone 'utc'`.as('fileCreatedAt'),
eb.fn('encode', ['asset.thumbhash', sql.lit('base64')]).as('thumbhash'),
'asset_exif.city',
'asset_exif.country',
'asset_exif.projectionType',
eb.fn
.coalesce(
eb
.case()
.when(sql`exif."exifImageHeight" = 0 or exif."exifImageWidth" = 0`)
.when(sql`asset_exif."exifImageHeight" = 0 or asset_exif."exifImageWidth" = 0`)
.then(eb.lit(1))
.when('exif.orientation', 'in', sql<string>`('5', '6', '7', '8', '-90', '90')`)
.then(sql`round(exif."exifImageHeight"::numeric / exif."exifImageWidth"::numeric, 3)`)
.else(sql`round(exif."exifImageWidth"::numeric / exif."exifImageHeight"::numeric, 3)`)
.when('asset_exif.orientation', 'in', sql<string>`('5', '6', '7', '8', '-90', '90')`)
.then(sql`round(asset_exif."exifImageHeight"::numeric / asset_exif."exifImageWidth"::numeric, 3)`)
.else(sql`round(asset_exif."exifImageWidth"::numeric / asset_exif."exifImageHeight"::numeric, 3)`)
.end(),
eb.lit(1),
)
.as('ratio'),
])
.where('assets.deletedAt', options.isTrashed ? 'is not' : 'is', null)
.where('asset.deletedAt', options.isTrashed ? 'is not' : 'is', null)
.$if(options.visibility == undefined, withDefaultVisibility)
.$if(!!options.visibility, (qb) => qb.where('assets.visibility', '=', options.visibility!))
.$if(!!options.visibility, (qb) => qb.where('asset.visibility', '=', options.visibility!))
.where(truncatedDate(), '=', timeBucket.replace(/^[+-]/, ''))
.$if(!!options.albumId, (qb) =>
qb.where((eb) =>
eb.exists(
eb
.selectFrom('albums_assets_assets')
.whereRef('albums_assets_assets.assetsId', '=', 'assets.id')
.where('albums_assets_assets.albumsId', '=', asUuid(options.albumId!)),
.selectFrom('album_asset')
.whereRef('album_asset.assetsId', '=', 'asset.id')
.where('album_asset.albumsId', '=', asUuid(options.albumId!)),
),
),
)
.$if(!!options.personId, (qb) => hasPeople(qb, [options.personId!]))
.$if(!!options.userIds, (qb) => qb.where('assets.ownerId', '=', anyUuid(options.userIds!)))
.$if(options.isFavorite !== undefined, (qb) => qb.where('assets.isFavorite', '=', options.isFavorite!))
.$if(!!options.userIds, (qb) => qb.where('asset.ownerId', '=', anyUuid(options.userIds!)))
.$if(options.isFavorite !== undefined, (qb) => qb.where('asset.isFavorite', '=', options.isFavorite!))
.$if(!!options.withStacked, (qb) =>
qb
.where((eb) =>
eb.not(
eb.exists(
eb
.selectFrom('asset_stack')
.whereRef('asset_stack.id', '=', 'assets.stackId')
.whereRef('asset_stack.primaryAssetId', '!=', 'assets.id'),
.selectFrom('stack')
.whereRef('stack.id', '=', 'asset.stackId')
.whereRef('stack.primaryAssetId', '!=', 'asset.id'),
),
),
)
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets as stacked')
.selectFrom('asset as stacked')
.select(sql`array[stacked."stackId"::text, count('stacked')::text]`.as('stack'))
.whereRef('stacked.stackId', '=', 'assets.stackId')
.whereRef('stacked.stackId', '=', 'asset.stackId')
.where('stacked.deletedAt', 'is', null)
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
.groupBy('stacked.stackId')
@ -615,13 +613,13 @@ export class AssetRepository {
)
.select('stack'),
)
.$if(!!options.assetType, (qb) => qb.where('assets.type', '=', options.assetType!))
.$if(!!options.assetType, (qb) => qb.where('asset.type', '=', options.assetType!))
.$if(options.isDuplicate !== undefined, (qb) =>
qb.where('assets.duplicateId', options.isDuplicate ? 'is not' : 'is', null),
qb.where('asset.duplicateId', options.isDuplicate ? 'is not' : 'is', null),
)
.$if(!!options.isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
.$if(!!options.tagId, (qb) => withTagId(qb, options.tagId!))
.orderBy('assets.fileCreatedAt', options.order ?? 'desc'),
.orderBy('asset.fileCreatedAt', options.order ?? 'desc'),
)
.with('agg', (qb) =>
qb
@ -660,17 +658,17 @@ export class AssetRepository {
const items = await this.db
.with('cities', (qb) =>
qb
.selectFrom('exif')
.selectFrom('asset_exif')
.select('city')
.where('city', 'is not', null)
.groupBy('city')
.having((eb) => eb.fn('count', [eb.ref('assetId')]), '>=', minAssetsPerField),
)
.selectFrom('assets')
.innerJoin('exif', 'assets.id', 'exif.assetId')
.innerJoin('cities', 'exif.city', 'cities.city')
.distinctOn('exif.city')
.select(['assetId as data', 'exif.city as value'])
.selectFrom('asset')
.innerJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.innerJoin('cities', 'asset_exif.city', 'cities.city')
.distinctOn('asset_exif.city')
.select(['assetId as data', 'asset_exif.city as value'])
.$narrowType<{ value: NotNull }>()
.where('ownerId', '=', asUuid(ownerId))
.where('visibility', '=', AssetVisibility.TIMELINE)
@ -695,27 +693,27 @@ export class AssetRepository {
getAllForUserFullSync(options: AssetFullSyncOptions) {
const { ownerId, lastId, updatedUntil, limit } = options;
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.$call(withExif)
.leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId')
.leftJoin('stack', 'stack.id', 'asset.stackId')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets as stacked')
.selectAll('asset_stack')
.selectFrom('asset as stacked')
.selectAll('stack')
.select((eb) => eb.fn.count(eb.table('stacked')).as('assetCount'))
.whereRef('stacked.stackId', '=', 'asset_stack.id')
.groupBy('asset_stack.id')
.whereRef('stacked.stackId', '=', 'stack.id')
.groupBy('stack.id')
.as('stacked_assets'),
(join) => join.on('asset_stack.id', 'is not', null),
(join) => join.on('stack.id', 'is not', null),
)
.select((eb) => eb.fn.toJson(eb.table('stacked_assets')).$castTo<Stack | null>().as('stack'))
.where('assets.ownerId', '=', asUuid(ownerId))
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('assets.updatedAt', '<=', updatedUntil)
.$if(!!lastId, (qb) => qb.where('assets.id', '>', lastId!))
.orderBy('assets.id')
.where('asset.ownerId', '=', asUuid(ownerId))
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.updatedAt', '<=', updatedUntil)
.$if(!!lastId, (qb) => qb.where('asset.id', '>', lastId!))
.orderBy('asset.id')
.limit(limit)
.execute();
}
@ -723,25 +721,25 @@ export class AssetRepository {
@GenerateSql({ params: [{ userIds: [DummyValue.UUID], updatedAfter: DummyValue.DATE, limit: 100 }] })
async getChangedDeltaSync(options: AssetDeltaSyncOptions) {
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.$call(withExif)
.leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId')
.leftJoin('stack', 'stack.id', 'asset.stackId')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets as stacked')
.selectAll('asset_stack')
.selectFrom('asset as stacked')
.selectAll('stack')
.select((eb) => eb.fn.count(eb.table('stacked')).as('assetCount'))
.whereRef('stacked.stackId', '=', 'asset_stack.id')
.groupBy('asset_stack.id')
.whereRef('stacked.stackId', '=', 'stack.id')
.groupBy('stack.id')
.as('stacked_assets'),
(join) => join.on('asset_stack.id', 'is not', null),
(join) => join.on('stack.id', 'is not', null),
)
.select((eb) => eb.fn.toJson(eb.table('stacked_assets').$castTo<Stack | null>()).as('stack'))
.where('assets.ownerId', '=', anyUuid(options.userIds))
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('assets.updatedAt', '>', options.updatedAfter)
.where('asset.ownerId', '=', anyUuid(options.userIds))
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.updatedAt', '>', options.updatedAfter)
.limit(options.limit)
.execute();
}
@ -749,7 +747,7 @@ export class AssetRepository {
async upsertFile(file: Pick<Insertable<AssetFileTable>, 'assetId' | 'path' | 'type'>): Promise<void> {
const value = { ...file, assetId: asUuid(file.assetId) };
await this.db
.insertInto('asset_files')
.insertInto('asset_file')
.values(value)
.onConflict((oc) =>
oc.columns(['assetId', 'type']).doUpdateSet((eb) => ({
@ -766,7 +764,7 @@ export class AssetRepository {
const values = files.map((row) => ({ ...row, assetId: asUuid(row.assetId) }));
await this.db
.insertInto('asset_files')
.insertInto('asset_file')
.values(values)
.onConflict((oc) =>
oc.columns(['assetId', 'type']).doUpdateSet((eb) => ({
@ -782,7 +780,7 @@ export class AssetRepository {
}
await this.db
.deleteFrom('asset_files')
.deleteFrom('asset_file')
.where('id', '=', anyUuid(files.map((file) => file.id)))
.execute();
}
@ -797,7 +795,7 @@ export class AssetRepository {
const exclusions = exclusionPatterns.map((pattern) => globToSqlPattern(pattern));
return this.db
.updateTable('assets')
.updateTable('asset')
.set({
isOffline: true,
deletedAt: new Date(),
@ -823,9 +821,9 @@ export class AssetRepository {
eb.not(
eb.exists(
this.db
.selectFrom('assets')
.selectFrom('asset')
.select('originalPath')
.whereRef('assets.originalPath', '=', eb.ref('path'))
.whereRef('asset.originalPath', '=', eb.ref('path'))
.where('libraryId', '=', asUuid(libraryId))
.where('isExternal', '=', true),
),
@ -838,7 +836,7 @@ export class AssetRepository {
async getLibraryAssetCount(libraryId: string): Promise<number> {
const { count } = await this.db
.selectFrom('assets')
.selectFrom('asset')
.select((eb) => eb.fn.countAll<number>().as('count'))
.where('libraryId', '=', asUuid(libraryId))
.executeTakeFirstOrThrow();

View File

@ -7,34 +7,34 @@ import { anyUuid } from 'src/utils/database';
const builder = (db: Kysely<DB>) =>
db
.selectFrom('assets')
.innerJoin('exif', 'assetId', 'id')
.select(['assets.id', 'assets.livePhotoVideoId', 'exif.fileSizeInByte as size'])
.where('assets.deletedAt', 'is', null);
.selectFrom('asset')
.innerJoin('asset_exif', 'assetId', 'id')
.select(['asset.id', 'asset.livePhotoVideoId', 'asset_exif.fileSizeInByte as size'])
.where('asset.deletedAt', 'is', null);
@Injectable()
export class DownloadRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}
downloadAssetIds(ids: string[]) {
return builder(this.db).where('assets.id', '=', anyUuid(ids)).stream();
return builder(this.db).where('asset.id', '=', anyUuid(ids)).stream();
}
downloadMotionAssetIds(ids: string[]) {
return builder(this.db).select(['assets.originalPath']).where('assets.id', '=', anyUuid(ids)).stream();
return builder(this.db).select(['asset.originalPath']).where('asset.id', '=', anyUuid(ids)).stream();
}
downloadAlbumId(albumId: string) {
return builder(this.db)
.innerJoin('albums_assets_assets', 'assets.id', 'albums_assets_assets.assetsId')
.where('albums_assets_assets.albumsId', '=', albumId)
.innerJoin('album_asset', 'asset.id', 'album_asset.assetsId')
.where('album_asset.albumsId', '=', albumId)
.stream();
}
downloadUserId(userId: string) {
return builder(this.db)
.where('assets.ownerId', '=', userId)
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.ownerId', '=', userId)
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
.stream();
}
}

View File

@ -32,28 +32,28 @@ export class DuplicateRepository {
this.db
.with('duplicates', (qb) =>
qb
.selectFrom('assets')
.selectFrom('asset')
.$call(withDefaultVisibility)
.leftJoinLateral(
(qb) =>
qb
.selectFrom('exif')
.selectAll('assets')
.select((eb) => eb.table('exif').as('exifInfo'))
.whereRef('exif.assetId', '=', 'assets.id')
.as('asset'),
.selectFrom('asset_exif')
.selectAll('asset')
.select((eb) => eb.table('asset_exif').as('exifInfo'))
.whereRef('asset_exif.assetId', '=', 'asset.id')
.as('asset2'),
(join) => join.onTrue(),
)
.select('assets.duplicateId')
.select('asset.duplicateId')
.select((eb) =>
eb.fn.jsonAgg('asset').orderBy('assets.localDateTime', 'asc').$castTo<MapAsset[]>().as('assets'),
eb.fn.jsonAgg('asset2').orderBy('asset.localDateTime', 'asc').$castTo<MapAsset[]>().as('assets'),
)
.where('assets.ownerId', '=', asUuid(userId))
.where('assets.duplicateId', 'is not', null)
.where('asset.ownerId', '=', asUuid(userId))
.where('asset.duplicateId', 'is not', null)
.$narrowType<{ duplicateId: NotNull }>()
.where('assets.deletedAt', 'is', null)
.where('assets.stackId', 'is', null)
.groupBy('assets.duplicateId'),
.where('asset.deletedAt', 'is', null)
.where('asset.stackId', 'is', null)
.groupBy('asset.duplicateId'),
)
.with('unique', (qb) =>
qb
@ -63,10 +63,10 @@ export class DuplicateRepository {
)
.with('removed_unique', (qb) =>
qb
.updateTable('assets')
.updateTable('asset')
.set({ duplicateId: null })
.from('unique')
.whereRef('assets.duplicateId', '=', 'unique.duplicateId'),
.whereRef('asset.duplicateId', '=', 'unique.duplicateId'),
)
.selectFrom('duplicates')
.selectAll()
@ -81,7 +81,7 @@ export class DuplicateRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
async delete(userId: string, id: string): Promise<void> {
await this.db
.updateTable('assets')
.updateTable('asset')
.set({ duplicateId: null })
.where('ownerId', '=', userId)
.where('duplicateId', '=', id)
@ -96,7 +96,7 @@ export class DuplicateRepository {
}
await this.db
.updateTable('assets')
.updateTable('asset')
.set({ duplicateId: null })
.where('ownerId', '=', userId)
.where('duplicateId', 'in', ids)
@ -120,19 +120,19 @@ export class DuplicateRepository {
return await trx
.with('cte', (qb) =>
qb
.selectFrom('assets')
.selectFrom('asset')
.$call(withDefaultVisibility)
.select([
'assets.id as assetId',
'assets.duplicateId',
'asset.id as assetId',
'asset.duplicateId',
sql<number>`smart_search.embedding <=> ${embedding}`.as('distance'),
])
.innerJoin('smart_search', 'assets.id', 'smart_search.assetId')
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.deletedAt', 'is', null)
.where('assets.type', '=', type)
.where('assets.id', '!=', asUuid(assetId))
.where('assets.stackId', 'is', null)
.innerJoin('smart_search', 'asset.id', 'smart_search.assetId')
.where('asset.ownerId', '=', anyUuid(userIds))
.where('asset.deletedAt', 'is', null)
.where('asset.type', '=', type)
.where('asset.id', '!=', asUuid(assetId))
.where('asset.stackId', 'is', null)
.orderBy('distance')
.limit(64),
)
@ -148,7 +148,7 @@ export class DuplicateRepository {
})
async merge(options: DuplicateMergeOptions): Promise<void> {
await this.db
.updateTable('assets')
.updateTable('asset')
.set({ duplicateId: options.targetId })
.where((eb) =>
eb.or([eb('duplicateId', '=', anyUuid(options.sourceIds)), eb('id', '=', anyUuid(options.assetIds))]),

View File

@ -21,50 +21,50 @@ export class LibraryRepository {
@GenerateSql({ params: [DummyValue.UUID] })
get(id: string, withDeleted = false) {
return this.db
.selectFrom('libraries')
.selectAll('libraries')
.where('libraries.id', '=', id)
.$if(!withDeleted, (qb) => qb.where('libraries.deletedAt', 'is', null))
.selectFrom('library')
.selectAll('library')
.where('library.id', '=', id)
.$if(!withDeleted, (qb) => qb.where('library.deletedAt', 'is', null))
.executeTakeFirst();
}
@GenerateSql({ params: [] })
getAll(withDeleted = false) {
return this.db
.selectFrom('libraries')
.selectAll('libraries')
.selectFrom('library')
.selectAll('library')
.orderBy('createdAt', 'asc')
.$if(!withDeleted, (qb) => qb.where('libraries.deletedAt', 'is', null))
.$if(!withDeleted, (qb) => qb.where('library.deletedAt', 'is', null))
.execute();
}
@GenerateSql()
getAllDeleted() {
return this.db
.selectFrom('libraries')
.selectAll('libraries')
.where('libraries.deletedAt', 'is not', null)
.selectFrom('library')
.selectAll('library')
.where('library.deletedAt', 'is not', null)
.orderBy('createdAt', 'asc')
.execute();
}
create(library: Insertable<LibraryTable>) {
return this.db.insertInto('libraries').values(library).returningAll().executeTakeFirstOrThrow();
return this.db.insertInto('library').values(library).returningAll().executeTakeFirstOrThrow();
}
async delete(id: string) {
await this.db.deleteFrom('libraries').where('libraries.id', '=', id).execute();
await this.db.deleteFrom('library').where('library.id', '=', id).execute();
}
async softDelete(id: string) {
await this.db.updateTable('libraries').set({ deletedAt: new Date() }).where('libraries.id', '=', id).execute();
await this.db.updateTable('library').set({ deletedAt: new Date() }).where('library.id', '=', id).execute();
}
update(id: string, library: Updateable<LibraryTable>) {
return this.db
.updateTable('libraries')
.updateTable('library')
.set(library)
.where('libraries.id', '=', id)
.where('library.id', '=', id)
.returningAll()
.executeTakeFirstOrThrow();
}
@ -72,14 +72,14 @@ export class LibraryRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined> {
const stats = await this.db
.selectFrom('libraries')
.innerJoin('assets', 'assets.libraryId', 'libraries.id')
.leftJoin('exif', 'exif.assetId', 'assets.id')
.selectFrom('library')
.innerJoin('asset', 'asset.libraryId', 'library.id')
.leftJoin('asset_exif', 'asset_exif.assetId', 'asset.id')
.select((eb) =>
eb.fn
.countAll<number>()
.filterWhere((eb) =>
eb.and([eb('assets.type', '=', AssetType.IMAGE), eb('assets.visibility', '!=', AssetVisibility.HIDDEN)]),
eb.and([eb('asset.type', '=', AssetType.IMAGE), eb('asset.visibility', '!=', AssetVisibility.HIDDEN)]),
)
.as('photos'),
)
@ -87,25 +87,25 @@ export class LibraryRepository {
eb.fn
.countAll<number>()
.filterWhere((eb) =>
eb.and([eb('assets.type', '=', AssetType.VIDEO), eb('assets.visibility', '!=', AssetVisibility.HIDDEN)]),
eb.and([eb('asset.type', '=', AssetType.VIDEO), eb('asset.visibility', '!=', AssetVisibility.HIDDEN)]),
)
.as('videos'),
)
.select((eb) => eb.fn.coalesce((eb) => eb.fn.sum('exif.fileSizeInByte'), eb.val(0)).as('usage'))
.groupBy('libraries.id')
.where('libraries.id', '=', id)
.select((eb) => eb.fn.coalesce((eb) => eb.fn.sum('asset_exif.fileSizeInByte'), eb.val(0)).as('usage'))
.groupBy('library.id')
.where('library.id', '=', id)
.executeTakeFirst();
// possibly a new library with 0 assets
if (!stats) {
const zero = sql<number>`0::int`;
return this.db
.selectFrom('libraries')
.selectFrom('library')
.select(zero.as('photos'))
.select(zero.as('videos'))
.select(zero.as('usage'))
.select(zero.as('total'))
.where('libraries.id', '=', id)
.where('library.id', '=', id)
.executeTakeFirst();
}
@ -118,6 +118,6 @@ export class LibraryRepository {
}
streamAssetIds(libraryId: string) {
return this.db.selectFrom('assets').select(['id']).where('libraryId', '=', libraryId).stream();
return this.db.selectFrom('asset').select(['id']).where('libraryId', '=', libraryId).stream();
}
}

View File

@ -83,25 +83,32 @@ export class MapRepository {
{ isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore }: MapMarkerSearchOptions = {},
) {
return this.db
.selectFrom('assets')
.innerJoin('exif', (builder) =>
.selectFrom('asset')
.innerJoin('asset_exif', (builder) =>
builder
.onRef('assets.id', '=', 'exif.assetId')
.on('exif.latitude', 'is not', null)
.on('exif.longitude', 'is not', null),
.onRef('asset.id', '=', 'asset_exif.assetId')
.on('asset_exif.latitude', 'is not', null)
.on('asset_exif.longitude', 'is not', null),
)
.select(['id', 'exif.latitude as lat', 'exif.longitude as lon', 'exif.city', 'exif.state', 'exif.country'])
.select([
'id',
'asset_exif.latitude as lat',
'asset_exif.longitude as lon',
'asset_exif.city',
'asset_exif.state',
'asset_exif.country',
])
.$narrowType<{ lat: NotNull; lon: NotNull }>()
.$if(isArchived === true, (qb) =>
qb.where((eb) =>
eb.or([
eb('assets.visibility', '=', AssetVisibility.TIMELINE),
eb('assets.visibility', '=', AssetVisibility.ARCHIVE),
eb('asset.visibility', '=', AssetVisibility.TIMELINE),
eb('asset.visibility', '=', AssetVisibility.ARCHIVE),
]),
),
)
.$if(isArchived === false || isArchived === undefined, (qb) =>
qb.where('assets.visibility', '=', AssetVisibility.TIMELINE),
qb.where('asset.visibility', '=', AssetVisibility.TIMELINE),
)
.$if(isFavorite !== undefined, (q) => q.where('isFavorite', '=', isFavorite!))
.$if(fileCreatedAfter !== undefined, (q) => q.where('fileCreatedAt', '>=', fileCreatedAfter!))
@ -118,9 +125,9 @@ export class MapRepository {
expression.push(
eb.exists((eb) =>
eb
.selectFrom('albums_assets_assets')
.whereRef('assets.id', '=', 'albums_assets_assets.assetsId')
.where('albums_assets_assets.albumsId', 'in', albumIds),
.selectFrom('album_asset')
.whereRef('asset.id', '=', 'album_asset.assetsId')
.where('album_asset.albumsId', 'in', albumIds),
),
);
}

View File

@ -16,14 +16,14 @@ export class MemoryRepository implements IBulkAsset {
async cleanup() {
await this.db
.deleteFrom('memories_assets_assets')
.using('assets')
.whereRef('memories_assets_assets.assetsId', '=', 'assets.id')
.where('assets.visibility', '!=', AssetVisibility.TIMELINE)
.deleteFrom('memory_asset')
.using('asset')
.whereRef('memory_asset.assetsId', '=', 'asset.id')
.where('asset.visibility', '!=', AssetVisibility.TIMELINE)
.execute();
return this.db
.deleteFrom('memories')
.deleteFrom('memory')
.where('createdAt', '<', DateTime.now().minus({ days: 30 }).toJSDate())
.where('isSaved', '=', false)
.execute();
@ -31,7 +31,7 @@ export class MemoryRepository implements IBulkAsset {
searchBuilder(ownerId: string, dto: MemorySearchDto) {
return this.db
.selectFrom('memories')
.selectFrom('memory')
.$if(dto.isSaved !== undefined, (qb) => qb.where('isSaved', '=', dto.isSaved!))
.$if(dto.type !== undefined, (qb) => qb.where('type', '=', dto.type!))
.$if(dto.for !== undefined, (qb) =>
@ -62,16 +62,16 @@ export class MemoryRepository implements IBulkAsset {
.select((eb) =>
jsonArrayFrom(
eb
.selectFrom('assets')
.selectAll('assets')
.innerJoin('memories_assets_assets', 'assets.id', 'memories_assets_assets.assetsId')
.whereRef('memories_assets_assets.memoriesId', '=', 'memories.id')
.orderBy('assets.fileCreatedAt', 'asc')
.where('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('assets.deletedAt', 'is', null),
.selectFrom('asset')
.selectAll('asset')
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetsId')
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
.orderBy('asset.fileCreatedAt', 'asc')
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('asset.deletedAt', 'is', null),
).as('assets'),
)
.selectAll('memories')
.selectAll('memory')
.orderBy('memoryAt', 'desc')
.execute();
}
@ -83,11 +83,11 @@ export class MemoryRepository implements IBulkAsset {
async create(memory: Insertable<MemoryTable>, assetIds: Set<string>) {
const id = await this.db.transaction().execute(async (tx) => {
const { id } = await tx.insertInto('memories').values(memory).returning('id').executeTakeFirstOrThrow();
const { id } = await tx.insertInto('memory').values(memory).returning('id').executeTakeFirstOrThrow();
if (assetIds.size > 0) {
const values = [...assetIds].map((assetId) => ({ memoriesId: id, assetsId: assetId }));
await tx.insertInto('memories_assets_assets').values(values).execute();
await tx.insertInto('memory_asset').values(values).execute();
}
return id;
@ -98,13 +98,13 @@ export class MemoryRepository implements IBulkAsset {
@GenerateSql({ params: [DummyValue.UUID, { ownerId: DummyValue.UUID, isSaved: true }] })
async update(id: string, memory: Updateable<MemoryTable>) {
await this.db.updateTable('memories').set(memory).where('id', '=', id).execute();
await this.db.updateTable('memory').set(memory).where('id', '=', id).execute();
return this.getByIdBuilder(id).executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID] })
async delete(id: string) {
await this.db.deleteFrom('memories').where('id', '=', id).execute();
await this.db.deleteFrom('memory').where('id', '=', id).execute();
}
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
@ -115,7 +115,7 @@ export class MemoryRepository implements IBulkAsset {
}
const results = await this.db
.selectFrom('memories_assets_assets')
.selectFrom('memory_asset')
.select(['assetsId'])
.where('memoriesId', '=', id)
.where('assetsId', 'in', assetIds)
@ -131,7 +131,7 @@ export class MemoryRepository implements IBulkAsset {
}
await this.db
.insertInto('memories_assets_assets')
.insertInto('memory_asset')
.values(assetIds.map((assetId) => ({ memoriesId: id, assetsId: assetId })))
.execute();
}
@ -143,27 +143,23 @@ export class MemoryRepository implements IBulkAsset {
return;
}
await this.db
.deleteFrom('memories_assets_assets')
.where('memoriesId', '=', id)
.where('assetsId', 'in', assetIds)
.execute();
await this.db.deleteFrom('memory_asset').where('memoriesId', '=', id).where('assetsId', 'in', assetIds).execute();
}
private getByIdBuilder(id: string) {
return this.db
.selectFrom('memories')
.selectAll('memories')
.selectFrom('memory')
.selectAll('memory')
.select((eb) =>
jsonArrayFrom(
eb
.selectFrom('assets')
.selectAll('assets')
.innerJoin('memories_assets_assets', 'assets.id', 'memories_assets_assets.assetsId')
.whereRef('memories_assets_assets.memoriesId', '=', 'memories.id')
.orderBy('assets.fileCreatedAt', 'asc')
.where('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('assets.deletedAt', 'is', null),
.selectFrom('asset')
.selectAll('asset')
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetsId')
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
.orderBy('asset.fileCreatedAt', 'asc')
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('asset.deletedAt', 'is', null),
).as('assets'),
)
.where('id', '=', id)

View File

@ -45,7 +45,7 @@ export class MoveRepository {
eb(
'move_history.entityId',
'not in',
eb.selectFrom('assets').select('id').whereRef('assets.id', '=', 'move_history.entityId'),
eb.selectFrom('asset').select('id').whereRef('asset.id', '=', 'move_history.entityId'),
),
)
.where('move_history.pathType', '=', sql.lit(AssetPathType.ORIGINAL))

View File

@ -12,7 +12,7 @@ export class NotificationRepository {
cleanup() {
return this.db
.deleteFrom('notifications')
.deleteFrom('notification')
.where((eb) =>
eb.or([
// remove soft-deleted notifications
@ -38,7 +38,7 @@ export class NotificationRepository {
@GenerateSql({ params: [DummyValue.UUID, {}] }, { name: 'unread', params: [DummyValue.UUID, { unread: true }] })
search(userId: string, dto: NotificationSearchDto) {
return this.db
.selectFrom('notifications')
.selectFrom('notification')
.select(columns.notification)
.where((qb) =>
qb.and({
@ -56,7 +56,7 @@ export class NotificationRepository {
create(notification: Insertable<NotificationTable>) {
return this.db
.insertInto('notifications')
.insertInto('notification')
.values(notification)
.returning(columns.notification)
.executeTakeFirstOrThrow();
@ -64,7 +64,7 @@ export class NotificationRepository {
get(id: string) {
return this.db
.selectFrom('notifications')
.selectFrom('notification')
.select(columns.notification)
.where('id', '=', id)
.where('deletedAt', 'is not', null)
@ -73,7 +73,7 @@ export class NotificationRepository {
update(id: string, notification: Updateable<NotificationTable>) {
return this.db
.updateTable('notifications')
.updateTable('notification')
.set(notification)
.where('deletedAt', 'is', null)
.where('id', '=', id)
@ -82,12 +82,12 @@ export class NotificationRepository {
}
async updateAll(ids: string[], notification: Updateable<NotificationTable>) {
await this.db.updateTable('notifications').set(notification).where('id', 'in', ids).execute();
await this.db.updateTable('notification').set(notification).where('id', 'in', ids).execute();
}
async delete(id: string) {
await this.db
.updateTable('notifications')
.updateTable('notification')
.set({ deletedAt: DateTime.now().toJSDate() })
.where('id', '=', id)
.execute();
@ -95,7 +95,7 @@ export class NotificationRepository {
async deleteAll(ids: string[]) {
await this.db
.updateTable('notifications')
.updateTable('notification')
.set({ deletedAt: DateTime.now().toJSDate() })
.where('id', 'in', ids)
.execute();

View File

@ -17,15 +17,15 @@ export enum PartnerDirection {
SharedWith = 'shared-with',
}
const withSharedBy = (eb: ExpressionBuilder<DB, 'partners'>) => {
const withSharedBy = (eb: ExpressionBuilder<DB, 'partner'>) => {
return jsonObjectFrom(
eb.selectFrom('users as sharedBy').select(columns.user).whereRef('sharedBy.id', '=', 'partners.sharedById'),
eb.selectFrom('user as sharedBy').select(columns.user).whereRef('sharedBy.id', '=', 'partner.sharedById'),
).as('sharedBy');
};
const withSharedWith = (eb: ExpressionBuilder<DB, 'partners'>) => {
const withSharedWith = (eb: ExpressionBuilder<DB, 'partner'>) => {
return jsonObjectFrom(
eb.selectFrom('users as sharedWith').select(columns.user).whereRef('sharedWith.id', '=', 'partners.sharedWithId'),
eb.selectFrom('user as sharedWith').select(columns.user).whereRef('sharedWith.id', '=', 'partner.sharedWithId'),
).as('sharedWith');
};
@ -50,7 +50,7 @@ export class PartnerRepository {
create(values: Insertable<PartnerTable>) {
return this.db
.insertInto('partners')
.insertInto('partner')
.values(values)
.returningAll()
.returning(withSharedBy)
@ -62,7 +62,7 @@ export class PartnerRepository {
@GenerateSql({ params: [{ sharedWithId: DummyValue.UUID, sharedById: DummyValue.UUID }, { inTimeline: true }] })
update({ sharedWithId, sharedById }: PartnerIds, values: Updateable<PartnerTable>) {
return this.db
.updateTable('partners')
.updateTable('partner')
.set(values)
.where('sharedWithId', '=', sharedWithId)
.where('sharedById', '=', sharedById)
@ -76,7 +76,7 @@ export class PartnerRepository {
@GenerateSql({ params: [{ sharedWithId: DummyValue.UUID, sharedById: DummyValue.UUID }] })
async remove({ sharedWithId, sharedById }: PartnerIds) {
await this.db
.deleteFrom('partners')
.deleteFrom('partner')
.where('sharedWithId', '=', sharedWithId)
.where('sharedById', '=', sharedById)
.execute();
@ -84,14 +84,14 @@ export class PartnerRepository {
private builder() {
return this.db
.selectFrom('partners')
.innerJoin('users as sharedBy', (join) =>
join.onRef('partners.sharedById', '=', 'sharedBy.id').on('sharedBy.deletedAt', 'is', null),
.selectFrom('partner')
.innerJoin('user as sharedBy', (join) =>
join.onRef('partner.sharedById', '=', 'sharedBy.id').on('sharedBy.deletedAt', 'is', null),
)
.innerJoin('users as sharedWith', (join) =>
join.onRef('partners.sharedWithId', '=', 'sharedWith.id').on('sharedWith.deletedAt', 'is', null),
.innerJoin('user as sharedWith', (join) =>
join.onRef('partner.sharedWithId', '=', 'sharedWith.id').on('sharedWith.deletedAt', 'is', null),
)
.selectAll('partners')
.selectAll('partner')
.select(withSharedBy)
.select(withSharedWith);
}

View File

@ -62,21 +62,21 @@ export type UnassignFacesOptions = DeleteFacesOptions;
export type SelectFaceOptions = (keyof Selectable<AssetFaceTable>)[];
const withPerson = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
const withPerson = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
return jsonObjectFrom(
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_faces.personId'),
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_face.personId'),
).as('person');
};
const withAsset = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
return jsonObjectFrom(
eb.selectFrom('assets').selectAll('assets').whereRef('assets.id', '=', 'asset_faces.assetId'),
).as('asset');
const withAsset = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
return jsonObjectFrom(eb.selectFrom('asset').selectAll('asset').whereRef('asset.id', '=', 'asset_face.assetId')).as(
'asset',
);
};
const withFaceSearch = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
const withFaceSearch = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
return jsonObjectFrom(
eb.selectFrom('face_search').selectAll('face_search').whereRef('face_search.faceId', '=', 'asset_faces.id'),
eb.selectFrom('face_search').selectAll('face_search').whereRef('face_search.faceId', '=', 'asset_face.id'),
).as('faceSearch');
};
@ -87,10 +87,10 @@ export class PersonRepository {
@GenerateSql({ params: [{ oldPersonId: DummyValue.UUID, newPersonId: DummyValue.UUID }] })
async reassignFaces({ oldPersonId, faceIds, newPersonId }: UpdateFacesData): Promise<number> {
const result = await this.db
.updateTable('asset_faces')
.updateTable('asset_face')
.set({ personId: newPersonId })
.$if(!!oldPersonId, (qb) => qb.where('asset_faces.personId', '=', oldPersonId!))
.$if(!!faceIds, (qb) => qb.where('asset_faces.id', 'in', faceIds!))
.$if(!!oldPersonId, (qb) => qb.where('asset_face.personId', '=', oldPersonId!))
.$if(!!faceIds, (qb) => qb.where('asset_face.id', 'in', faceIds!))
.executeTakeFirst();
return Number(result.numChangedRows ?? 0);
@ -98,9 +98,9 @@ export class PersonRepository {
async unassignFaces({ sourceType }: UnassignFacesOptions): Promise<void> {
await this.db
.updateTable('asset_faces')
.updateTable('asset_face')
.set({ personId: null })
.where('asset_faces.sourceType', '=', sourceType)
.where('asset_face.sourceType', '=', sourceType)
.execute();
}
@ -115,18 +115,18 @@ export class PersonRepository {
}
async deleteFaces({ sourceType }: DeleteFacesOptions): Promise<void> {
await this.db.deleteFrom('asset_faces').where('asset_faces.sourceType', '=', sourceType).execute();
await this.db.deleteFrom('asset_face').where('asset_face.sourceType', '=', sourceType).execute();
}
getAllFaces(options: GetAllFacesOptions = {}) {
return this.db
.selectFrom('asset_faces')
.selectAll('asset_faces')
.$if(options.personId === null, (qb) => qb.where('asset_faces.personId', 'is', null))
.$if(!!options.personId, (qb) => qb.where('asset_faces.personId', '=', options.personId!))
.$if(!!options.sourceType, (qb) => qb.where('asset_faces.sourceType', '=', options.sourceType!))
.$if(!!options.assetId, (qb) => qb.where('asset_faces.assetId', '=', options.assetId!))
.where('asset_faces.deletedAt', 'is', null)
.selectFrom('asset_face')
.selectAll('asset_face')
.$if(options.personId === null, (qb) => qb.where('asset_face.personId', 'is', null))
.$if(!!options.personId, (qb) => qb.where('asset_face.personId', '=', options.personId!))
.$if(!!options.sourceType, (qb) => qb.where('asset_face.sourceType', '=', options.sourceType!))
.$if(!!options.assetId, (qb) => qb.where('asset_face.assetId', '=', options.assetId!))
.where('asset_face.deletedAt', 'is', null)
.stream();
}
@ -147,21 +147,21 @@ export class PersonRepository {
const items = await this.db
.selectFrom('person')
.selectAll('person')
.innerJoin('asset_faces', 'asset_faces.personId', 'person.id')
.innerJoin('assets', (join) =>
.innerJoin('asset_face', 'asset_face.personId', 'person.id')
.innerJoin('asset', (join) =>
join
.onRef('asset_faces.assetId', '=', 'assets.id')
.on('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.on('assets.deletedAt', 'is', null),
.onRef('asset_face.assetId', '=', 'asset.id')
.on('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.on('asset.deletedAt', 'is', null),
)
.where('person.ownerId', '=', userId)
.where('asset_faces.deletedAt', 'is', null)
.where('asset_face.deletedAt', 'is', null)
.orderBy('person.isHidden', 'asc')
.orderBy('person.isFavorite', 'desc')
.having((eb) =>
eb.or([
eb('person.name', '!=', ''),
eb((innerEb) => innerEb.fn.count('asset_faces.assetId'), '>=', options?.minimumFaceCount || 1),
eb((innerEb) => innerEb.fn.count('asset_face.assetId'), '>=', options?.minimumFaceCount || 1),
]),
)
.groupBy('person.id')
@ -185,7 +185,7 @@ export class PersonRepository {
.$if(!options?.closestFaceAssetId, (qb) =>
qb
.orderBy(sql`NULLIF(person.name, '') is null`, 'asc')
.orderBy((eb) => eb.fn.count('asset_faces.assetId'), 'desc')
.orderBy((eb) => eb.fn.count('asset_face.assetId'), 'desc')
.orderBy(sql`NULLIF(person.name, '')`, (om) => om.asc().nullsLast())
.orderBy('person.createdAt'),
)
@ -202,9 +202,9 @@ export class PersonRepository {
return this.db
.selectFrom('person')
.selectAll('person')
.leftJoin('asset_faces', 'asset_faces.personId', 'person.id')
.where('asset_faces.deletedAt', 'is', null)
.having((eb) => eb.fn.count('asset_faces.assetId'), '=', 0)
.leftJoin('asset_face', 'asset_face.personId', 'person.id')
.where('asset_face.deletedAt', 'is', null)
.having((eb) => eb.fn.count('asset_face.assetId'), '=', 0)
.groupBy('person.id')
.execute();
}
@ -212,12 +212,12 @@ export class PersonRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getFaces(assetId: string) {
return this.db
.selectFrom('asset_faces')
.selectAll('asset_faces')
.selectFrom('asset_face')
.selectAll('asset_face')
.select(withPerson)
.where('asset_faces.assetId', '=', assetId)
.where('asset_faces.deletedAt', 'is', null)
.orderBy('asset_faces.boundingBoxX1', 'asc')
.where('asset_face.assetId', '=', assetId)
.where('asset_face.deletedAt', 'is', null)
.orderBy('asset_face.boundingBoxX1', 'asc')
.execute();
}
@ -225,30 +225,30 @@ export class PersonRepository {
getFaceById(id: string) {
// TODO return null instead of find or fail
return this.db
.selectFrom('asset_faces')
.selectAll('asset_faces')
.selectFrom('asset_face')
.selectAll('asset_face')
.select(withPerson)
.where('asset_faces.id', '=', id)
.where('asset_faces.deletedAt', 'is', null)
.where('asset_face.id', '=', id)
.where('asset_face.deletedAt', 'is', null)
.executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID] })
getFaceForFacialRecognitionJob(id: string) {
return this.db
.selectFrom('asset_faces')
.select(['asset_faces.id', 'asset_faces.personId', 'asset_faces.sourceType'])
.selectFrom('asset_face')
.select(['asset_face.id', 'asset_face.personId', 'asset_face.sourceType'])
.select((eb) =>
jsonObjectFrom(
eb
.selectFrom('assets')
.select(['assets.ownerId', 'assets.visibility', 'assets.fileCreatedAt'])
.whereRef('assets.id', '=', 'asset_faces.assetId'),
.selectFrom('asset')
.select(['asset.ownerId', 'asset.visibility', 'asset.fileCreatedAt'])
.whereRef('asset.id', '=', 'asset_face.assetId'),
).as('asset'),
)
.select(withFaceSearch)
.where('asset_faces.id', '=', id)
.where('asset_faces.deletedAt', 'is', null)
.where('asset_face.id', '=', id)
.where('asset_face.deletedAt', 'is', null)
.executeTakeFirst();
}
@ -256,40 +256,40 @@ export class PersonRepository {
getDataForThumbnailGenerationJob(id: string) {
return this.db
.selectFrom('person')
.innerJoin('asset_faces', 'asset_faces.id', 'person.faceAssetId')
.innerJoin('assets', 'asset_faces.assetId', 'assets.id')
.leftJoin('exif', 'exif.assetId', 'assets.id')
.innerJoin('asset_face', 'asset_face.id', 'person.faceAssetId')
.innerJoin('asset', 'asset_face.assetId', 'asset.id')
.leftJoin('asset_exif', 'asset_exif.assetId', 'asset.id')
.select([
'person.ownerId',
'asset_faces.boundingBoxX1 as x1',
'asset_faces.boundingBoxY1 as y1',
'asset_faces.boundingBoxX2 as x2',
'asset_faces.boundingBoxY2 as y2',
'asset_faces.imageWidth as oldWidth',
'asset_faces.imageHeight as oldHeight',
'assets.type',
'assets.originalPath',
'exif.orientation as exifOrientation',
'asset_face.boundingBoxX1 as x1',
'asset_face.boundingBoxY1 as y1',
'asset_face.boundingBoxX2 as x2',
'asset_face.boundingBoxY2 as y2',
'asset_face.imageWidth as oldWidth',
'asset_face.imageHeight as oldHeight',
'asset.type',
'asset.originalPath',
'asset_exif.orientation as exifOrientation',
])
.select((eb) =>
eb
.selectFrom('asset_files')
.select('asset_files.path')
.whereRef('asset_files.assetId', '=', 'assets.id')
.where('asset_files.type', '=', sql.lit(AssetFileType.PREVIEW))
.selectFrom('asset_file')
.select('asset_file.path')
.whereRef('asset_file.assetId', '=', 'asset.id')
.where('asset_file.type', '=', sql.lit(AssetFileType.PREVIEW))
.as('previewPath'),
)
.where('person.id', '=', id)
.where('asset_faces.deletedAt', 'is', null)
.where('asset_face.deletedAt', 'is', null)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
async reassignFace(assetFaceId: string, newPersonId: string): Promise<number> {
const result = await this.db
.updateTable('asset_faces')
.updateTable('asset_face')
.set({ personId: newPersonId })
.where('asset_faces.id', '=', assetFaceId)
.where('asset_face.id', '=', assetFaceId)
.executeTakeFirst();
return Number(result.numChangedRows ?? 0);
@ -336,16 +336,16 @@ export class PersonRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getStatistics(personId: string): Promise<PersonStatistics> {
const result = await this.db
.selectFrom('asset_faces')
.leftJoin('assets', (join) =>
.selectFrom('asset_face')
.leftJoin('asset', (join) =>
join
.onRef('assets.id', '=', 'asset_faces.assetId')
.on('asset_faces.personId', '=', personId)
.on('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.on('assets.deletedAt', 'is', null),
.onRef('asset.id', '=', 'asset_face.assetId')
.on('asset_face.personId', '=', personId)
.on('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.on('asset.deletedAt', 'is', null),
)
.select((eb) => eb.fn.count(eb.fn('distinct', ['assets.id'])).as('count'))
.where('asset_faces.deletedAt', 'is', null)
.select((eb) => eb.fn.count(eb.fn('distinct', ['asset.id'])).as('count'))
.where('asset_face.deletedAt', 'is', null)
.executeTakeFirst();
return {
@ -361,16 +361,16 @@ export class PersonRepository {
.where((eb) =>
eb.exists((eb) =>
eb
.selectFrom('asset_faces')
.whereRef('asset_faces.personId', '=', 'person.id')
.where('asset_faces.deletedAt', 'is', null)
.selectFrom('asset_face')
.whereRef('asset_face.personId', '=', 'person.id')
.where('asset_face.deletedAt', 'is', null)
.where((eb) =>
eb.exists((eb) =>
eb
.selectFrom('assets')
.whereRef('assets.id', '=', 'asset_faces.assetId')
.where('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('assets.deletedAt', 'is', null),
.selectFrom('asset')
.whereRef('asset.id', '=', 'asset_face.assetId')
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
.where('asset.deletedAt', 'is', null),
),
),
),
@ -402,12 +402,12 @@ export class PersonRepository {
): Promise<void> {
let query = this.db;
if (facesToAdd.length > 0) {
(query as any) = query.with('added', (db) => db.insertInto('asset_faces').values(facesToAdd));
(query as any) = query.with('added', (db) => db.insertInto('asset_face').values(facesToAdd));
}
if (faceIdsToRemove.length > 0) {
(query as any) = query.with('removed', (db) =>
db.deleteFrom('asset_faces').where('asset_faces.id', '=', (eb) => eb.fn.any(eb.val(faceIdsToRemove))),
db.deleteFrom('asset_face').where('asset_face.id', '=', (eb) => eb.fn.any(eb.val(faceIdsToRemove))),
);
}
@ -469,23 +469,23 @@ export class PersonRepository {
}
return this.db
.selectFrom('asset_faces')
.selectAll('asset_faces')
.selectFrom('asset_face')
.selectAll('asset_face')
.select(withAsset)
.select(withPerson)
.where('asset_faces.assetId', 'in', assetIds)
.where('asset_faces.personId', 'in', personIds)
.where('asset_faces.deletedAt', 'is', null)
.where('asset_face.assetId', 'in', assetIds)
.where('asset_face.personId', 'in', personIds)
.where('asset_face.deletedAt', 'is', null)
.execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
getRandomFace(personId: string) {
return this.db
.selectFrom('asset_faces')
.selectAll('asset_faces')
.where('asset_faces.personId', '=', personId)
.where('asset_faces.deletedAt', 'is', null)
.selectFrom('asset_face')
.selectAll('asset_face')
.where('asset_face.personId', '=', personId)
.where('asset_face.deletedAt', 'is', null)
.executeTakeFirst();
}
@ -500,22 +500,22 @@ export class PersonRepository {
}
async createAssetFace(face: Insertable<AssetFaceTable>): Promise<void> {
await this.db.insertInto('asset_faces').values(face).execute();
await this.db.insertInto('asset_face').values(face).execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async deleteAssetFace(id: string): Promise<void> {
await this.db.deleteFrom('asset_faces').where('asset_faces.id', '=', id).execute();
await this.db.deleteFrom('asset_face').where('asset_face.id', '=', id).execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async softDeleteAssetFaces(id: string): Promise<void> {
await this.db.updateTable('asset_faces').set({ deletedAt: new Date() }).where('asset_faces.id', '=', id).execute();
await this.db.updateTable('asset_face').set({ deletedAt: new Date() }).where('asset_face.id', '=', id).execute();
}
async vacuum({ reindexVectors }: { reindexVectors: boolean }): Promise<void> {
await sql`VACUUM ANALYZE asset_faces, face_search, person`.execute(this.db);
await sql`REINDEX TABLE asset_faces`.execute(this.db);
await sql`VACUUM ANALYZE asset_face, face_search, person`.execute(this.db);
await sql`REINDEX TABLE asset_face`.execute(this.db);
await sql`REINDEX TABLE person`.execute(this.db);
if (reindexVectors) {
await sql`REINDEX TABLE face_search`.execute(this.db);

View File

@ -7,7 +7,7 @@ import { MapAsset } from 'src/dtos/asset-response.dto';
import { AssetStatus, AssetType, AssetVisibility, VectorIndex } from 'src/enum';
import { probes } from 'src/repositories/database.repository';
import { DB } from 'src/schema';
import { ExifTable } from 'src/schema/tables/exif.table';
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { anyUuid, searchAssetBuilder } from 'src/utils/database';
import { paginationHelper } from 'src/utils/pagination';
import { isValidInteger } from 'src/validation';
@ -183,8 +183,8 @@ export class SearchRepository {
async searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions) {
const orderDirection = (options.orderDirection?.toLowerCase() || 'desc') as OrderByDirection;
const items = await searchAssetBuilder(this.db, options)
.selectAll('assets')
.orderBy('assets.fileCreatedAt', orderDirection)
.selectAll('asset')
.orderBy('asset.fileCreatedAt', orderDirection)
.limit(pagination.size + 1)
.offset((pagination.page - 1) * pagination.size)
.execute();
@ -224,13 +224,13 @@ export class SearchRepository {
const uuid = randomUUID();
const builder = searchAssetBuilder(this.db, options);
const lessThan = builder
.selectAll('assets')
.where('assets.id', '<', uuid)
.selectAll('asset')
.where('asset.id', '<', uuid)
.orderBy(sql`random()`)
.limit(size);
const greaterThan = builder
.selectAll('assets')
.where('assets.id', '>', uuid)
.selectAll('asset')
.where('asset.id', '>', uuid)
.orderBy(sql`random()`)
.limit(size);
const { rows } = await sql<MapAsset>`${lessThan} union all ${greaterThan} limit ${size}`.execute(this.db);
@ -258,8 +258,8 @@ export class SearchRepository {
return this.db.transaction().execute(async (trx) => {
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.CLIP])}`.execute(trx);
const items = await searchAssetBuilder(trx, options)
.selectAll('assets')
.innerJoin('smart_search', 'assets.id', 'smart_search.assetId')
.selectAll('asset')
.innerJoin('smart_search', 'asset.id', 'smart_search.assetId')
.orderBy(sql`smart_search.embedding <=> ${options.embedding}`)
.limit(pagination.size + 1)
.offset((pagination.page - 1) * pagination.size)
@ -288,18 +288,18 @@ export class SearchRepository {
return await trx
.with('cte', (qb) =>
qb
.selectFrom('asset_faces')
.selectFrom('asset_face')
.select([
'asset_faces.id',
'asset_faces.personId',
'asset_face.id',
'asset_face.personId',
sql<number>`face_search.embedding <=> ${embedding}`.as('distance'),
])
.innerJoin('assets', 'assets.id', 'asset_faces.assetId')
.innerJoin('face_search', 'face_search.faceId', 'asset_faces.id')
.leftJoin('person', 'person.id', 'asset_faces.personId')
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.deletedAt', 'is', null)
.$if(!!hasPerson, (qb) => qb.where('asset_faces.personId', 'is not', null))
.innerJoin('asset', 'asset.id', 'asset_face.assetId')
.innerJoin('face_search', 'face_search.faceId', 'asset_face.id')
.leftJoin('person', 'person.id', 'asset_face.personId')
.where('asset.ownerId', '=', anyUuid(userIds))
.where('asset.deletedAt', 'is', null)
.$if(!!hasPerson, (qb) => qb.where('asset_face.personId', 'is not', null))
.$if(!!minBirthDate, (qb) =>
qb.where((eb) =>
eb.or([eb('person.birthDate', 'is', null), eb('person.birthDate', '<=', minBirthDate!)]),
@ -347,13 +347,13 @@ export class SearchRepository {
return this.db
.withRecursive('cte', (qb) => {
const base = qb
.selectFrom('exif')
.selectFrom('asset_exif')
.select(['city', 'assetId'])
.innerJoin('assets', 'assets.id', 'exif.assetId')
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.visibility', '=', AssetVisibility.TIMELINE)
.where('assets.type', '=', AssetType.IMAGE)
.where('assets.deletedAt', 'is', null)
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
.where('asset.ownerId', '=', anyUuid(userIds))
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
.where('asset.type', '=', AssetType.IMAGE)
.where('asset.deletedAt', 'is', null)
.orderBy('city')
.limit(1);
@ -363,14 +363,14 @@ export class SearchRepository {
.innerJoinLateral(
(qb) =>
qb
.selectFrom('exif')
.selectFrom('asset_exif')
.select(['city', 'assetId'])
.innerJoin('assets', 'assets.id', 'exif.assetId')
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.visibility', '=', AssetVisibility.TIMELINE)
.where('assets.type', '=', AssetType.IMAGE)
.where('assets.deletedAt', 'is', null)
.whereRef('exif.city', '>', 'cte.city')
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
.where('asset.ownerId', '=', anyUuid(userIds))
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
.where('asset.type', '=', AssetType.IMAGE)
.where('asset.deletedAt', 'is', null)
.whereRef('asset_exif.city', '>', 'cte.city')
.orderBy('city')
.limit(1)
.as('l'),
@ -379,17 +379,17 @@ export class SearchRepository {
return sql<{ city: string; assetId: string }>`(${base} union all ${recursive})`;
})
.selectFrom('assets')
.innerJoin('exif', 'assets.id', 'exif.assetId')
.innerJoin('cte', 'assets.id', 'cte.assetId')
.selectAll('assets')
.selectFrom('asset')
.innerJoin('asset_exif', 'asset.id', 'asset_exif.assetId')
.innerJoin('cte', 'asset.id', 'cte.assetId')
.selectAll('asset')
.select((eb) =>
eb
.fn('to_jsonb', [eb.table('exif')])
.$castTo<Selectable<ExifTable>>()
.fn('to_jsonb', [eb.table('asset_exif')])
.$castTo<Selectable<AssetExifTable>>()
.as('exifInfo'),
)
.orderBy('exif.city')
.orderBy('asset_exif.city')
.execute();
}
@ -445,10 +445,10 @@ export class SearchRepository {
private getExifField<K extends 'city' | 'state' | 'country' | 'make' | 'model'>(field: K, userIds: string[]) {
return this.db
.selectFrom('exif')
.selectFrom('asset_exif')
.select(field)
.distinctOn(field)
.innerJoin('assets', 'assets.id', 'exif.assetId')
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
.where('ownerId', '=', anyUuid(userIds))
.where('visibility', '=', AssetVisibility.TIMELINE)
.where('deletedAt', 'is', null)

View File

@ -17,7 +17,7 @@ export class SessionRepository {
cleanup() {
return this.db
.deleteFrom('sessions')
.deleteFrom('session')
.where((eb) =>
eb.or([
eb('updatedAt', '<=', DateTime.now().minus({ days: 90 }).toJSDate()),
@ -31,7 +31,7 @@ export class SessionRepository {
@GenerateSql({ params: [DummyValue.UUID] })
get(id: string) {
return this.db
.selectFrom('sessions')
.selectFrom('session')
.select(['id', 'expiresAt', 'pinExpiresAt'])
.where('id', '=', id)
.executeTakeFirst();
@ -40,20 +40,20 @@ export class SessionRepository {
@GenerateSql({ params: [DummyValue.STRING] })
getByToken(token: string) {
return this.db
.selectFrom('sessions')
.selectFrom('session')
.select((eb) => [
...columns.authSession,
jsonObjectFrom(
eb
.selectFrom('users')
.selectFrom('user')
.select(columns.authUser)
.whereRef('users.id', '=', 'sessions.userId')
.where('users.deletedAt', 'is', null),
.whereRef('user.id', '=', 'session.userId')
.where('user.deletedAt', 'is', null),
).as('user'),
])
.where('sessions.token', '=', token)
.where('session.token', '=', token)
.where((eb) =>
eb.or([eb('sessions.expiresAt', 'is', null), eb('sessions.expiresAt', '>', DateTime.now().toJSDate())]),
eb.or([eb('session.expiresAt', 'is', null), eb('session.expiresAt', '>', DateTime.now().toJSDate())]),
)
.executeTakeFirst();
}
@ -61,47 +61,47 @@ export class SessionRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getByUserId(userId: string) {
return this.db
.selectFrom('sessions')
.innerJoin('users', (join) => join.onRef('users.id', '=', 'sessions.userId').on('users.deletedAt', 'is', null))
.selectAll('sessions')
.where('sessions.userId', '=', userId)
.selectFrom('session')
.innerJoin('user', (join) => join.onRef('user.id', '=', 'session.userId').on('user.deletedAt', 'is', null))
.selectAll('session')
.where('session.userId', '=', userId)
.where((eb) =>
eb.or([eb('sessions.expiresAt', 'is', null), eb('sessions.expiresAt', '>', DateTime.now().toJSDate())]),
eb.or([eb('session.expiresAt', 'is', null), eb('session.expiresAt', '>', DateTime.now().toJSDate())]),
)
.orderBy('sessions.updatedAt', 'desc')
.orderBy('sessions.createdAt', 'desc')
.orderBy('session.updatedAt', 'desc')
.orderBy('session.createdAt', 'desc')
.execute();
}
create(dto: Insertable<SessionTable>) {
return this.db.insertInto('sessions').values(dto).returningAll().executeTakeFirstOrThrow();
return this.db.insertInto('session').values(dto).returningAll().executeTakeFirstOrThrow();
}
update(id: string, dto: Updateable<SessionTable>) {
return this.db
.updateTable('sessions')
.updateTable('session')
.set(dto)
.where('sessions.id', '=', asUuid(id))
.where('session.id', '=', asUuid(id))
.returningAll()
.executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID] })
async delete(id: string) {
await this.db.deleteFrom('sessions').where('id', '=', asUuid(id)).execute();
await this.db.deleteFrom('session').where('id', '=', asUuid(id)).execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async lockAll(userId: string) {
await this.db.updateTable('sessions').set({ pinExpiresAt: null }).where('userId', '=', userId).execute();
await this.db.updateTable('session').set({ pinExpiresAt: null }).where('userId', '=', userId).execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async resetSyncProgress(sessionId: string) {
await this.db.transaction().execute((tx) => {
return Promise.all([
tx.updateTable('sessions').set({ isPendingSyncReset: false }).where('id', '=', sessionId).execute(),
tx.deleteFrom('session_sync_checkpoints').where('sessionId', '=', sessionId).execute(),
tx.updateTable('session').set({ isPendingSyncReset: false }).where('id', '=', sessionId).execute(),
tx.deleteFrom('session_sync_checkpoint').where('sessionId', '=', sessionId).execute(),
]);
});
}

View File

@ -22,61 +22,66 @@ export class SharedLinkRepository {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
get(userId: string, id: string) {
return this.db
.selectFrom('shared_links')
.selectAll('shared_links')
.selectFrom('shared_link')
.selectAll('shared_link')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('shared_link__asset')
.whereRef('shared_links.id', '=', 'shared_link__asset.sharedLinksId')
.innerJoin('assets', 'assets.id', 'shared_link__asset.assetsId')
.where('assets.deletedAt', 'is', null)
.selectAll('assets')
.selectFrom('shared_link_asset')
.whereRef('shared_link.id', '=', 'shared_link_asset.sharedLinksId')
.innerJoin('asset', 'asset.id', 'shared_link_asset.assetsId')
.where('asset.deletedAt', 'is', null)
.selectAll('asset')
.innerJoinLateral(
(eb) => eb.selectFrom('exif').selectAll('exif').whereRef('exif.assetId', '=', 'assets.id').as('exifInfo'),
(eb) =>
eb
.selectFrom('asset_exif')
.selectAll('asset_exif')
.whereRef('asset_exif.assetId', '=', 'asset.id')
.as('exifInfo'),
(join) => join.onTrue(),
)
.select((eb) => eb.fn.toJson('exifInfo').as('exifInfo'))
.orderBy('assets.fileCreatedAt', 'asc')
.orderBy('asset.fileCreatedAt', 'asc')
.as('a'),
(join) => join.onTrue(),
)
.leftJoinLateral(
(eb) =>
eb
.selectFrom('albums')
.selectAll('albums')
.whereRef('albums.id', '=', 'shared_links.albumId')
.where('albums.deletedAt', 'is', null)
.leftJoin('albums_assets_assets', 'albums_assets_assets.albumsId', 'albums.id')
.selectFrom('album')
.selectAll('album')
.whereRef('album.id', '=', 'shared_link.albumId')
.where('album.deletedAt', 'is', null)
.leftJoin('album_asset', 'album_asset.albumsId', 'album.id')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets')
.selectAll('assets')
.whereRef('albums_assets_assets.assetsId', '=', 'assets.id')
.where('assets.deletedAt', 'is', null)
.selectFrom('asset')
.selectAll('asset')
.whereRef('album_asset.assetsId', '=', 'asset.id')
.where('asset.deletedAt', 'is', null)
.innerJoinLateral(
(eb) =>
eb
.selectFrom('exif')
.selectAll('exif')
.whereRef('exif.assetId', '=', 'assets.id')
.as('assets_exifInfo'),
.selectFrom('asset_exif')
.selectAll('asset_exif')
.whereRef('asset_exif.assetId', '=', 'asset.id')
.as('exifInfo'),
(join) => join.onTrue(),
)
.select((eb) => eb.fn.toJson(eb.table('assets_exifInfo')).as('exifInfo'))
.orderBy('assets.fileCreatedAt', 'asc')
.select((eb) => eb.fn.toJson(eb.table('exifInfo')).as('exifInfo'))
.orderBy('asset.fileCreatedAt', 'asc')
.as('assets'),
(join) => join.onTrue(),
)
.innerJoinLateral(
(eb) =>
eb
.selectFrom('users')
.selectAll('users')
.whereRef('users.id', '=', 'albums.ownerId')
.where('users.deletedAt', 'is', null)
.selectFrom('user')
.selectAll('user')
.whereRef('user.id', '=', 'album.ownerId')
.where('user.deletedAt', 'is', null)
.as('owner'),
(join) => join.onTrue(),
)
@ -84,7 +89,7 @@ export class SharedLinkRepository {
eb.fn.coalesce(eb.fn.jsonAgg('assets').filterWhere('assets.id', 'is not', null), sql`'[]'`).as('assets'),
)
.select((eb) => eb.fn.toJson('owner').as('owner'))
.groupBy(['albums.id', sql`"owner".*`])
.groupBy(['album.id', sql`"owner".*`])
.as('album'),
(join) => join.onTrue(),
)
@ -94,29 +99,29 @@ export class SharedLinkRepository {
.$castTo<MapAsset[]>()
.as('assets'),
)
.groupBy(['shared_links.id', sql`"album".*`])
.groupBy(['shared_link.id', sql`"album".*`])
.select((eb) => eb.fn.toJson('album').$castTo<Album | null>().as('album'))
.where('shared_links.id', '=', id)
.where('shared_links.userId', '=', userId)
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
.orderBy('shared_links.createdAt', 'desc')
.where('shared_link.id', '=', id)
.where('shared_link.userId', '=', userId)
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
.orderBy('shared_link.createdAt', 'desc')
.executeTakeFirst();
}
@GenerateSql({ params: [{ userId: DummyValue.UUID, albumId: DummyValue.UUID }] })
getAll({ userId, albumId }: SharedLinkSearchOptions) {
return this.db
.selectFrom('shared_links')
.selectAll('shared_links')
.where('shared_links.userId', '=', userId)
.leftJoin('shared_link__asset', 'shared_link__asset.sharedLinksId', 'shared_links.id')
.selectFrom('shared_link')
.selectAll('shared_link')
.where('shared_link.userId', '=', userId)
.leftJoin('shared_link_asset', 'shared_link_asset.sharedLinksId', 'shared_link.id')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets')
.select((eb) => eb.fn.jsonAgg('assets').as('assets'))
.whereRef('assets.id', '=', 'shared_link__asset.assetsId')
.where('assets.deletedAt', 'is', null)
.selectFrom('asset')
.select((eb) => eb.fn.jsonAgg('asset').as('assets'))
.whereRef('asset.id', '=', 'shared_link_asset.assetsId')
.where('asset.deletedAt', 'is', null)
.as('assets'),
(join) => join.onTrue(),
)
@ -125,75 +130,75 @@ export class SharedLinkRepository {
.leftJoinLateral(
(eb) =>
eb
.selectFrom('albums')
.selectAll('albums')
.whereRef('albums.id', '=', 'shared_links.albumId')
.selectFrom('album')
.selectAll('album')
.whereRef('album.id', '=', 'shared_link.albumId')
.innerJoinLateral(
(eb) =>
eb
.selectFrom('users')
.selectFrom('user')
.select([
'users.id',
'users.email',
'users.createdAt',
'users.profileImagePath',
'users.isAdmin',
'users.shouldChangePassword',
'users.deletedAt',
'users.oauthId',
'users.updatedAt',
'users.storageLabel',
'users.name',
'users.quotaSizeInBytes',
'users.quotaUsageInBytes',
'users.status',
'users.profileChangedAt',
'user.id',
'user.email',
'user.createdAt',
'user.profileImagePath',
'user.isAdmin',
'user.shouldChangePassword',
'user.deletedAt',
'user.oauthId',
'user.updatedAt',
'user.storageLabel',
'user.name',
'user.quotaSizeInBytes',
'user.quotaUsageInBytes',
'user.status',
'user.profileChangedAt',
])
.whereRef('users.id', '=', 'albums.ownerId')
.where('users.deletedAt', 'is', null)
.whereRef('user.id', '=', 'album.ownerId')
.where('user.deletedAt', 'is', null)
.as('owner'),
(join) => join.onTrue(),
)
.select((eb) => eb.fn.toJson('owner').as('owner'))
.where('albums.deletedAt', 'is', null)
.where('album.deletedAt', 'is', null)
.as('album'),
(join) => join.onTrue(),
)
.select((eb) => eb.fn.toJson('album').$castTo<Album | null>().as('album'))
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
.$if(!!albumId, (eb) => eb.where('shared_links.albumId', '=', albumId!))
.orderBy('shared_links.createdAt', 'desc')
.distinctOn(['shared_links.createdAt'])
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
.$if(!!albumId, (eb) => eb.where('shared_link.albumId', '=', albumId!))
.orderBy('shared_link.createdAt', 'desc')
.distinctOn(['shared_link.createdAt'])
.execute();
}
@GenerateSql({ params: [DummyValue.BUFFER] })
async getByKey(key: Buffer) {
return this.db
.selectFrom('shared_links')
.where('shared_links.key', '=', key)
.leftJoin('albums', 'albums.id', 'shared_links.albumId')
.where('albums.deletedAt', 'is', null)
.selectFrom('shared_link')
.where('shared_link.key', '=', key)
.leftJoin('album', 'album.id', 'shared_link.albumId')
.where('album.deletedAt', 'is', null)
.select((eb) => [
...columns.authSharedLink,
jsonObjectFrom(
eb.selectFrom('users').select(columns.authUser).whereRef('users.id', '=', 'shared_links.userId'),
eb.selectFrom('user').select(columns.authUser).whereRef('user.id', '=', 'shared_link.userId'),
).as('user'),
])
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('albums.id', 'is not', null)]))
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
.executeTakeFirst();
}
async create(entity: Insertable<SharedLinkTable> & { assetIds?: string[] }) {
const { id } = await this.db
.insertInto('shared_links')
.insertInto('shared_link')
.values(_.omit(entity, 'assetIds'))
.returningAll()
.executeTakeFirstOrThrow();
if (entity.assetIds && entity.assetIds.length > 0) {
await this.db
.insertInto('shared_link__asset')
.insertInto('shared_link_asset')
.values(entity.assetIds!.map((assetsId) => ({ assetsId, sharedLinksId: id })))
.execute();
}
@ -203,15 +208,15 @@ export class SharedLinkRepository {
async update(entity: Updateable<SharedLinkTable> & { id: string; assetIds?: string[] }) {
const { id } = await this.db
.updateTable('shared_links')
.updateTable('shared_link')
.set(_.omit(entity, 'assets', 'album', 'assetIds'))
.where('shared_links.id', '=', entity.id)
.where('shared_link.id', '=', entity.id)
.returningAll()
.executeTakeFirstOrThrow();
if (entity.assetIds && entity.assetIds.length > 0) {
await this.db
.insertInto('shared_link__asset')
.insertInto('shared_link_asset')
.values(entity.assetIds!.map((assetsId) => ({ assetsId, sharedLinksId: id })))
.execute();
}
@ -220,23 +225,24 @@ export class SharedLinkRepository {
}
async remove(id: string): Promise<void> {
await this.db.deleteFrom('shared_links').where('shared_links.id', '=', id).execute();
await this.db.deleteFrom('shared_link').where('shared_link.id', '=', id).execute();
}
private getSharedLinks(id: string) {
return this.db
.selectFrom('shared_links')
.selectAll('shared_links')
.where('shared_links.id', '=', id)
.leftJoin('shared_link__asset', 'shared_link__asset.sharedLinksId', 'shared_links.id')
.selectFrom('shared_link')
.selectAll('shared_link')
.where('shared_link.id', '=', id)
.leftJoin('shared_link_asset', 'shared_link_asset.sharedLinksId', 'shared_link.id')
.leftJoinLateral(
(eb) =>
eb
.selectFrom('assets')
.whereRef('assets.id', '=', 'shared_link__asset.assetsId')
.selectAll('assets')
.selectFrom('asset')
.whereRef('asset.id', '=', 'shared_link_asset.assetsId')
.selectAll('asset')
.innerJoinLateral(
(eb) => eb.selectFrom('exif').whereRef('exif.assetId', '=', 'assets.id').selectAll().as('exif'),
(eb) =>
eb.selectFrom('asset_exif').whereRef('asset_exif.assetId', '=', 'asset.id').selectAll().as('exif'),
(join) => join.onTrue(),
)
.as('assets'),
@ -248,7 +254,7 @@ export class SharedLinkRepository {
.$castTo<MapAsset[]>()
.as('assets'),
)
.groupBy('shared_links.id')
.groupBy('shared_link.id')
.executeTakeFirstOrThrow();
}
}

View File

@ -13,29 +13,34 @@ export interface StackSearch {
primaryAssetId?: string;
}
const withAssets = (eb: ExpressionBuilder<DB, 'asset_stack'>, withTags = false) => {
const withAssets = (eb: ExpressionBuilder<DB, 'stack'>, withTags = false) => {
return jsonArrayFrom(
eb
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.innerJoinLateral(
(eb) => eb.selectFrom('exif').select(columns.exif).whereRef('exif.assetId', '=', 'assets.id').as('exifInfo'),
(eb) =>
eb
.selectFrom('asset_exif')
.select(columns.exif)
.whereRef('asset_exif.assetId', '=', 'asset.id')
.as('exifInfo'),
(join) => join.onTrue(),
)
.$if(withTags, (eb) =>
eb.select((eb) =>
jsonArrayFrom(
eb
.selectFrom('tags')
.selectFrom('tag')
.select(columns.tag)
.innerJoin('tag_asset', 'tags.id', 'tag_asset.tagsId')
.whereRef('tag_asset.assetsId', '=', 'assets.id'),
.innerJoin('tag_asset', 'tag.id', 'tag_asset.tagsId')
.whereRef('tag_asset.assetsId', '=', 'asset.id'),
).as('tags'),
),
)
.select((eb) => eb.fn.toJson('exifInfo').as('exifInfo'))
.where('assets.deletedAt', 'is', null)
.whereRef('assets.stackId', '=', 'asset_stack.id')
.where('asset.deletedAt', 'is', null)
.whereRef('asset.stackId', '=', 'stack.id')
.$call(withDefaultVisibility),
).as('assets');
};
@ -47,28 +52,28 @@ export class StackRepository {
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
search(query: StackSearch) {
return this.db
.selectFrom('asset_stack')
.selectAll('asset_stack')
.selectFrom('stack')
.selectAll('stack')
.select(withAssets)
.where('asset_stack.ownerId', '=', query.ownerId)
.$if(!!query.primaryAssetId, (eb) => eb.where('asset_stack.primaryAssetId', '=', query.primaryAssetId!))
.where('stack.ownerId', '=', query.ownerId)
.$if(!!query.primaryAssetId, (eb) => eb.where('stack.primaryAssetId', '=', query.primaryAssetId!))
.execute();
}
async create(entity: Omit<Insertable<StackTable>, 'primaryAssetId'>, assetIds: string[]) {
return this.db.transaction().execute(async (tx) => {
const stacks = await tx
.selectFrom('asset_stack')
.where('asset_stack.ownerId', '=', entity.ownerId)
.where('asset_stack.primaryAssetId', 'in', assetIds)
.select('asset_stack.id')
.selectFrom('stack')
.where('stack.ownerId', '=', entity.ownerId)
.where('stack.primaryAssetId', 'in', assetIds)
.select('stack.id')
.select((eb) =>
jsonArrayFrom(
eb
.selectFrom('assets')
.select('assets.id')
.whereRef('assets.stackId', '=', 'asset_stack.id')
.where('assets.deletedAt', 'is', null),
.selectFrom('asset')
.select('asset.id')
.whereRef('asset.stackId', '=', 'stack.id')
.where('asset.deletedAt', 'is', null),
).as('assets'),
)
.execute();
@ -86,7 +91,7 @@ export class StackRepository {
if (stacks.length > 0) {
await tx
.deleteFrom('asset_stack')
.deleteFrom('stack')
.where(
'id',
'in',
@ -96,13 +101,13 @@ export class StackRepository {
}
const newRecord = await tx
.insertInto('asset_stack')
.insertInto('stack')
.values({ ...entity, primaryAssetId: assetIds[0] })
.returning('id')
.executeTakeFirstOrThrow();
await tx
.updateTable('assets')
.updateTable('asset')
.set({
stackId: newRecord.id,
updatedAt: new Date(),
@ -111,8 +116,8 @@ export class StackRepository {
.execute();
return tx
.selectFrom('asset_stack')
.selectAll('asset_stack')
.selectFrom('stack')
.selectAll('stack')
.select(withAssets)
.where('id', '=', newRecord.id)
.executeTakeFirstOrThrow();
@ -121,19 +126,19 @@ export class StackRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async delete(id: string): Promise<void> {
await this.db.deleteFrom('asset_stack').where('id', '=', asUuid(id)).execute();
await this.db.deleteFrom('stack').where('id', '=', asUuid(id)).execute();
}
async deleteAll(ids: string[]): Promise<void> {
await this.db.deleteFrom('asset_stack').where('id', 'in', ids).execute();
await this.db.deleteFrom('stack').where('id', 'in', ids).execute();
}
update(id: string, entity: Updateable<StackTable>) {
return this.db
.updateTable('asset_stack')
.updateTable('stack')
.set(entity)
.where('id', '=', asUuid(id))
.returningAll('asset_stack')
.returningAll('stack')
.returning((eb) => withAssets(eb, true))
.executeTakeFirstOrThrow();
}
@ -141,7 +146,7 @@ export class StackRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getById(id: string) {
return this.db
.selectFrom('asset_stack')
.selectFrom('stack')
.selectAll()
.select((eb) => withAssets(eb, true))
.where('id', '=', asUuid(id))

View File

@ -13,7 +13,7 @@ export class SyncCheckpointRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getAll(sessionId: string) {
return this.db
.selectFrom('session_sync_checkpoints')
.selectFrom('session_sync_checkpoint')
.select(['type', 'ack'])
.where('sessionId', '=', sessionId)
.execute();
@ -21,7 +21,7 @@ export class SyncCheckpointRepository {
upsertAll(items: Insertable<SessionSyncCheckpointTable>[]) {
return this.db
.insertInto('session_sync_checkpoints')
.insertInto('session_sync_checkpoint')
.values(items)
.onConflict((oc) =>
oc.columns(['sessionId', 'type']).doUpdateSet((eb) => ({
@ -34,7 +34,7 @@ export class SyncCheckpointRepository {
@GenerateSql({ params: [DummyValue.UUID] })
deleteAll(sessionId: string, types?: SyncEntityType[]) {
return this.db
.deleteFrom('session_sync_checkpoints')
.deleteFrom('session_sync_checkpoint')
.where('sessionId', '=', sessionId)
.$if(!!types, (qb) => qb.where('type', 'in', types!))
.execute();

View File

@ -7,27 +7,27 @@ import { DB } from 'src/schema';
import { SyncAck } from 'src/types';
type AuditTables =
| 'users_audit'
| 'partners_audit'
| 'assets_audit'
| 'albums_audit'
| 'album_users_audit'
| 'album_assets_audit'
| 'memories_audit'
| 'memory_assets_audit'
| 'stacks_audit'
| 'user_audit'
| 'partner_audit'
| 'asset_audit'
| 'album_audit'
| 'album_user_audit'
| 'album_asset_audit'
| 'memory_audit'
| 'memory_asset_audit'
| 'stack_audit'
| 'person_audit'
| 'user_metadata_audit';
type UpsertTables =
| 'users'
| 'partners'
| 'assets'
| 'exif'
| 'albums'
| 'albums_shared_users_users'
| 'memories'
| 'memories_assets_assets'
| 'asset_stack'
| 'user'
| 'partner'
| 'asset'
| 'asset_exif'
| 'album'
| 'album_user'
| 'memory'
| 'memory_asset'
| 'stack'
| 'person'
| 'user_metadata';
@ -100,7 +100,7 @@ class AlbumSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
getCreatedAfter(userId: string, afterCreateId?: string) {
return this.db
.selectFrom('albums_shared_users_users')
.selectFrom('album_user')
.select(['albumsId as id', 'createId'])
.where('usersId', '=', userId)
.$if(!!afterCreateId, (qb) => qb.where('createId', '>=', afterCreateId!))
@ -112,7 +112,7 @@ class AlbumSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('albums_audit')
.selectFrom('album_audit')
.select(['id', 'albumId'])
.where('userId', '=', userId)
.$call(this.auditTableFilters(ack))
@ -122,24 +122,24 @@ class AlbumSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('albums')
.distinctOn(['albums.id', 'albums.updateId'])
.where('albums.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('albums.updateId', '>', ack!.updateId))
.orderBy('albums.updateId', 'asc')
.leftJoin('albums_shared_users_users as album_users', 'albums.id', 'album_users.albumsId')
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
.selectFrom('album')
.distinctOn(['album.id', 'album.updateId'])
.where('album.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('album.updateId', '>', ack!.updateId))
.orderBy('album.updateId', 'asc')
.leftJoin('album_user as album_users', 'album.id', 'album_users.albumsId')
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
.select([
'albums.id',
'albums.ownerId',
'albums.albumName as name',
'albums.description',
'albums.createdAt',
'albums.updatedAt',
'albums.albumThumbnailAssetId as thumbnailAssetId',
'albums.isActivityEnabled',
'albums.order',
'albums.updateId',
'album.id',
'album.ownerId',
'album.albumName as name',
'album.description',
'album.createdAt',
'album.updatedAt',
'album.albumThumbnailAssetId as thumbnailAssetId',
'album.isActivityEnabled',
'album.order',
'album.updateId',
])
.stream();
}
@ -149,31 +149,31 @@ class AlbumAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('assets')
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'assets.id')
.selectFrom('asset')
.innerJoin('album_asset', 'album_asset.assetsId', 'asset.id')
.select(columns.syncAsset)
.select('assets.updateId')
.where('album_assets.albumsId', '=', albumId)
.where('assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('assets.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('assets.updateId', '>=', afterUpdateId!))
.orderBy('assets.updateId', 'asc')
.select('asset.updateId')
.where('album_asset.albumsId', '=', albumId)
.where('asset.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('asset.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('asset.updateId', '>=', afterUpdateId!))
.orderBy('asset.updateId', 'asc')
.stream();
}
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('assets')
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'assets.id')
.selectFrom('asset')
.innerJoin('album_asset', 'album_asset.assetsId', 'asset.id')
.select(columns.syncAsset)
.select('assets.updateId')
.where('assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('assets.updateId', '>', ack!.updateId))
.orderBy('assets.updateId', 'asc')
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
.select('asset.updateId')
.where('asset.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('asset.updateId', '>', ack!.updateId))
.orderBy('asset.updateId', 'asc')
.innerJoin('album', 'album.id', 'album_asset.albumsId')
.leftJoin('album_user', 'album_user.albumsId', 'album_asset.albumsId')
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('album_user.usersId', '=', userId)]))
.stream();
}
}
@ -182,31 +182,31 @@ class AlbumAssetExifSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('exif')
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'exif.assetId')
.selectFrom('asset_exif')
.innerJoin('album_asset', 'album_asset.assetsId', 'asset_exif.assetId')
.select(columns.syncAssetExif)
.select('exif.updateId')
.where('album_assets.albumsId', '=', albumId)
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('exif.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('exif.updateId', '>=', afterUpdateId!))
.orderBy('exif.updateId', 'asc')
.select('asset_exif.updateId')
.where('album_asset.albumsId', '=', albumId)
.where('asset_exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('asset_exif.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('asset_exif.updateId', '>=', afterUpdateId!))
.orderBy('asset_exif.updateId', 'asc')
.stream();
}
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('exif')
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'exif.assetId')
.selectFrom('asset_exif')
.innerJoin('album_asset', 'album_asset.assetsId', 'asset_exif.assetId')
.select(columns.syncAssetExif)
.select('exif.updateId')
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('exif.updateId', '>', ack!.updateId))
.orderBy('exif.updateId', 'asc')
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
.select('asset_exif.updateId')
.where('asset_exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('asset_exif.updateId', '>', ack!.updateId))
.orderBy('asset_exif.updateId', 'asc')
.innerJoin('album', 'album.id', 'album_asset.albumsId')
.leftJoin('album_user', 'album_user.albumsId', 'album_asset.albumsId')
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('album_user.usersId', '=', userId)]))
.stream();
}
}
@ -215,7 +215,7 @@ class AlbumToAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('albums_assets_assets as album_assets')
.selectFrom('album_asset as album_assets')
.select(['album_assets.assetsId as assetId', 'album_assets.albumsId as albumId', 'album_assets.updateId'])
.where('album_assets.albumsId', '=', albumId)
.where('album_assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
@ -228,22 +228,22 @@ class AlbumToAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('album_assets_audit')
.selectFrom('album_asset_audit')
.select(['id', 'assetId', 'albumId'])
.where((eb) =>
eb(
'albumId',
'in',
eb
.selectFrom('albums')
.selectFrom('album')
.select(['id'])
.where('ownerId', '=', userId)
.union((eb) =>
eb.parens(
eb
.selectFrom('albums_shared_users_users as albumUsers')
.select(['albumUsers.albumsId as id'])
.where('albumUsers.usersId', '=', userId),
.selectFrom('album_user')
.select(['album_user.albumsId as id'])
.where('album_user.usersId', '=', userId),
),
),
),
@ -255,14 +255,14 @@ class AlbumToAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('albums_assets_assets as album_assets')
.select(['album_assets.assetsId as assetId', 'album_assets.albumsId as albumId', 'album_assets.updateId'])
.where('album_assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('album_assets.updateId', '>', ack!.updateId))
.orderBy('album_assets.updateId', 'asc')
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
.selectFrom('album_asset')
.select(['album_asset.assetsId as assetId', 'album_asset.albumsId as albumId', 'album_asset.updateId'])
.where('album_asset.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('album_asset.updateId', '>', ack!.updateId))
.orderBy('album_asset.updateId', 'asc')
.innerJoin('album', 'album.id', 'album_asset.albumsId')
.leftJoin('album_user', 'album_user.albumsId', 'album_asset.albumsId')
.where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('album_user.usersId', '=', userId)]))
.stream();
}
}
@ -271,9 +271,9 @@ class AlbumUserSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('albums_shared_users_users as album_users')
.selectFrom('album_user')
.select(columns.syncAlbumUser)
.select('album_users.updateId')
.select('album_user.updateId')
.where('albumsId', '=', albumId)
.where('updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('updateId', '<=', beforeUpdateId)
@ -285,22 +285,22 @@ class AlbumUserSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('album_users_audit')
.selectFrom('album_user_audit')
.select(['id', 'userId', 'albumId'])
.where((eb) =>
eb(
'albumId',
'in',
eb
.selectFrom('albums')
.selectFrom('album')
.select(['id'])
.where('ownerId', '=', userId)
.union((eb) =>
eb.parens(
eb
.selectFrom('albums_shared_users_users as albumUsers')
.select(['albumUsers.albumsId as id'])
.where('albumUsers.usersId', '=', userId),
.selectFrom('album_user')
.select(['album_user.albumsId as id'])
.where('album_user.usersId', '=', userId),
),
),
),
@ -312,24 +312,24 @@ class AlbumUserSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('albums_shared_users_users as album_users')
.selectFrom('album_user')
.select(columns.syncAlbumUser)
.select('album_users.updateId')
.where('album_users.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('album_users.updateId', '>', ack!.updateId))
.orderBy('album_users.updateId', 'asc')
.select('album_user.updateId')
.where('album_user.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.$if(!!ack, (qb) => qb.where('album_user.updateId', '>', ack!.updateId))
.orderBy('album_user.updateId', 'asc')
.where((eb) =>
eb(
'album_users.albumsId',
'album_user.albumsId',
'in',
eb
.selectFrom('albums')
.selectFrom('album')
.select(['id'])
.where('ownerId', '=', userId)
.union((eb) =>
eb.parens(
eb
.selectFrom('albums_shared_users_users as albumUsers')
.selectFrom('album_user as albumUsers')
.select(['albumUsers.albumsId as id'])
.where('albumUsers.usersId', '=', userId),
),
@ -344,7 +344,7 @@ class AssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('assets_audit')
.selectFrom('asset_audit')
.select(['id', 'assetId'])
.where('ownerId', '=', userId)
.$call(this.auditTableFilters(ack))
@ -354,9 +354,9 @@ class AssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(columns.syncAsset)
.select('assets.updateId')
.select('asset.updateId')
.where('ownerId', '=', userId)
.$call(this.upsertTableFilters(ack))
.stream();
@ -402,10 +402,10 @@ class AssetExifSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('exif')
.selectFrom('asset_exif')
.select(columns.syncAssetExif)
.select('exif.updateId')
.where('assetId', 'in', (eb) => eb.selectFrom('assets').select('id').where('ownerId', '=', userId))
.select('asset_exif.updateId')
.where('assetId', 'in', (eb) => eb.selectFrom('asset').select('id').where('ownerId', '=', userId))
.$call(this.upsertTableFilters(ack))
.stream();
}
@ -415,7 +415,7 @@ class MemorySync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('memories_audit')
.selectFrom('memory_audit')
.select(['id', 'memoryId'])
.where('userId', '=', userId)
.$call(this.auditTableFilters(ack))
@ -425,7 +425,7 @@ class MemorySync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('memories')
.selectFrom('memory')
.select([
'id',
'createdAt',
@ -451,9 +451,9 @@ class MemoryToAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('memory_assets_audit')
.selectFrom('memory_asset_audit')
.select(['id', 'memoryId', 'assetId'])
.where('memoryId', 'in', (eb) => eb.selectFrom('memories').select('id').where('ownerId', '=', userId))
.where('memoryId', 'in', (eb) => eb.selectFrom('memory').select('id').where('ownerId', '=', userId))
.$call(this.auditTableFilters(ack))
.stream();
}
@ -461,10 +461,10 @@ class MemoryToAssetSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('memories_assets_assets')
.selectFrom('memory_asset')
.select(['memoriesId as memoryId', 'assetsId as assetId'])
.select('updateId')
.where('memoriesId', 'in', (eb) => eb.selectFrom('memories').select('id').where('ownerId', '=', userId))
.where('memoriesId', 'in', (eb) => eb.selectFrom('memory').select('id').where('ownerId', '=', userId))
.$call(this.upsertTableFilters(ack))
.stream();
}
@ -474,19 +474,19 @@ class PartnerSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
getCreatedAfter(userId: string, afterCreateId?: string) {
return this.db
.selectFrom('partners')
.selectFrom('partner')
.select(['sharedById', 'createId'])
.where('sharedWithId', '=', userId)
.$if(!!afterCreateId, (qb) => qb.where('createId', '>=', afterCreateId!))
.where('createdAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.orderBy('partners.createId', 'asc')
.orderBy('partner.createId', 'asc')
.execute();
}
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('partners_audit')
.selectFrom('partner_audit')
.select(['id', 'sharedById', 'sharedWithId'])
.where((eb) => eb.or([eb('sharedById', '=', userId), eb('sharedWithId', '=', userId)]))
.$call(this.auditTableFilters(ack))
@ -496,7 +496,7 @@ class PartnerSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('partners')
.selectFrom('partner')
.select(['sharedById', 'sharedWithId', 'inTimeline', 'updateId'])
.where((eb) => eb.or([eb('sharedById', '=', userId), eb('sharedWithId', '=', userId)]))
.$call(this.upsertTableFilters(ack))
@ -508,9 +508,9 @@ class PartnerAssetsSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(partnerId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(columns.syncAsset)
.select('assets.updateId')
.select('asset.updateId')
.where('ownerId', '=', partnerId)
.where('updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('updateId', '<=', beforeUpdateId)
@ -522,10 +522,10 @@ class PartnerAssetsSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('assets_audit')
.selectFrom('asset_audit')
.select(['id', 'assetId'])
.where('ownerId', 'in', (eb) =>
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
eb.selectFrom('partner').select(['sharedById']).where('sharedWithId', '=', userId),
)
.$call(this.auditTableFilters(ack))
.stream();
@ -534,11 +534,11 @@ class PartnerAssetsSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('assets')
.selectFrom('asset')
.select(columns.syncAsset)
.select('assets.updateId')
.select('asset.updateId')
.where('ownerId', 'in', (eb) =>
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
eb.selectFrom('partner').select(['sharedById']).where('sharedWithId', '=', userId),
)
.$call(this.upsertTableFilters(ack))
.stream();
@ -549,30 +549,30 @@ class PartnerAssetExifsSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(partnerId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('exif')
.selectFrom('asset_exif')
.select(columns.syncAssetExif)
.select('exif.updateId')
.innerJoin('assets', 'assets.id', 'exif.assetId')
.where('assets.ownerId', '=', partnerId)
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('exif.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('exif.updateId', '>=', afterUpdateId!))
.orderBy('exif.updateId', 'asc')
.select('asset_exif.updateId')
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
.where('asset.ownerId', '=', partnerId)
.where('asset_exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.where('asset_exif.updateId', '<=', beforeUpdateId)
.$if(!!afterUpdateId, (eb) => eb.where('asset_exif.updateId', '>=', afterUpdateId!))
.orderBy('asset_exif.updateId', 'asc')
.stream();
}
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('exif')
.selectFrom('asset_exif')
.select(columns.syncAssetExif)
.select('exif.updateId')
.select('asset_exif.updateId')
.where('assetId', 'in', (eb) =>
eb
.selectFrom('assets')
.selectFrom('asset')
.select('id')
.where('ownerId', 'in', (eb) =>
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
eb.selectFrom('partner').select(['sharedById']).where('sharedWithId', '=', userId),
),
)
.$call(this.upsertTableFilters(ack))
@ -584,7 +584,7 @@ class StackSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('stacks_audit')
.selectFrom('stack_audit')
.select(['id', 'stackId'])
.where('userId', '=', userId)
.$call(this.auditTableFilters(ack))
@ -594,7 +594,7 @@ class StackSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('asset_stack')
.selectFrom('stack')
.select(columns.syncStack)
.select('updateId')
.where('ownerId', '=', userId)
@ -607,11 +607,9 @@ class PartnerStackSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getDeletes(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('stacks_audit')
.selectFrom('stack_audit')
.select(['id', 'stackId'])
.where('userId', 'in', (eb) =>
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
)
.where('userId', 'in', (eb) => eb.selectFrom('partner').select(['sharedById']).where('sharedWithId', '=', userId))
.$call(this.auditTableFilters(ack))
.stream();
}
@ -619,7 +617,7 @@ class PartnerStackSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
getBackfill(partnerId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
return this.db
.selectFrom('asset_stack')
.selectFrom('stack')
.select(columns.syncStack)
.select('updateId')
.where('ownerId', '=', partnerId)
@ -633,11 +631,11 @@ class PartnerStackSync extends BaseSync {
@GenerateSql({ params: [DummyValue.UUID], stream: true })
getUpserts(userId: string, ack?: SyncAck) {
return this.db
.selectFrom('asset_stack')
.selectFrom('stack')
.select(columns.syncStack)
.select('updateId')
.where('ownerId', 'in', (eb) =>
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
eb.selectFrom('partner').select(['sharedById']).where('sharedWithId', '=', userId),
)
.$call(this.upsertTableFilters(ack))
.stream();
@ -647,13 +645,13 @@ class PartnerStackSync extends BaseSync {
class UserSync extends BaseSync {
@GenerateSql({ params: [], stream: true })
getDeletes(ack?: SyncAck) {
return this.db.selectFrom('users_audit').select(['id', 'userId']).$call(this.auditTableFilters(ack)).stream();
return this.db.selectFrom('user_audit').select(['id', 'userId']).$call(this.auditTableFilters(ack)).stream();
}
@GenerateSql({ params: [], stream: true })
getUpserts(ack?: SyncAck) {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(['id', 'name', 'email', 'deletedAt', 'updateId'])
.$call(this.upsertTableFilters(ack))
.stream();

View File

@ -19,13 +19,13 @@ export class TagRepository {
@GenerateSql({ params: [DummyValue.UUID] })
get(id: string) {
return this.db.selectFrom('tags').select(columns.tag).where('id', '=', id).executeTakeFirst();
return this.db.selectFrom('tag').select(columns.tag).where('id', '=', id).executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
getByValue(userId: string, value: string) {
return this.db
.selectFrom('tags')
.selectFrom('tag')
.select(columns.tag)
.where('userId', '=', userId)
.where('value', '=', value)
@ -37,7 +37,7 @@ export class TagRepository {
const parentId = _parentId ?? null;
return this.db.transaction().execute(async (tx) => {
const tag = await this.db
.insertInto('tags')
.insertInto('tag')
.values({ userId, value, parentId })
.onConflict((oc) => oc.columns(['userId', 'value']).doUpdateSet({ parentId }))
.returning(columns.tag)
@ -45,18 +45,18 @@ export class TagRepository {
// update closure table
await tx
.insertInto('tags_closure')
.insertInto('tag_closure')
.values({ id_ancestor: tag.id, id_descendant: tag.id })
.onConflict((oc) => oc.doNothing())
.execute();
if (parentId) {
await tx
.insertInto('tags_closure')
.insertInto('tag_closure')
.columns(['id_ancestor', 'id_descendant'])
.expression(
this.db
.selectFrom('tags_closure')
.selectFrom('tag_closure')
.select(['id_ancestor', sql.raw<string>(`'${tag.id}'`).as('id_descendant')])
.where('id_descendant', '=', parentId),
)
@ -70,22 +70,22 @@ export class TagRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getAll(userId: string) {
return this.db.selectFrom('tags').select(columns.tag).where('userId', '=', userId).orderBy('value').execute();
return this.db.selectFrom('tag').select(columns.tag).where('userId', '=', userId).orderBy('value').execute();
}
@GenerateSql({ params: [{ userId: DummyValue.UUID, color: DummyValue.STRING, value: DummyValue.STRING }] })
create(tag: Insertable<TagTable>) {
return this.db.insertInto('tags').values(tag).returningAll().executeTakeFirstOrThrow();
return this.db.insertInto('tag').values(tag).returningAll().executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID, { color: DummyValue.STRING }] })
update(id: string, dto: Updateable<TagTable>) {
return this.db.updateTable('tags').set(dto).where('id', '=', id).returningAll().executeTakeFirstOrThrow();
return this.db.updateTable('tag').set(dto).where('id', '=', id).returningAll().executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID] })
async delete(id: string) {
await this.db.deleteFrom('tags').where('id', '=', id).execute();
await this.db.deleteFrom('tag').where('id', '=', id).execute();
}
@ChunkedSet({ paramIndex: 1 })
@ -166,17 +166,17 @@ export class TagRepository {
// TODO rewrite as a single statement
await this.db.transaction().execute(async (tx) => {
const result = await tx
.selectFrom('assets')
.innerJoin('tag_asset', 'tag_asset.assetsId', 'assets.id')
.innerJoin('tags_closure', 'tags_closure.id_descendant', 'tag_asset.tagsId')
.innerJoin('tags', 'tags.id', 'tags_closure.id_descendant')
.select((eb) => ['tags.id', eb.fn.count<number>('assets.id').as('count')])
.groupBy('tags.id')
.selectFrom('asset')
.innerJoin('tag_asset', 'tag_asset.assetsId', 'asset.id')
.innerJoin('tag_closure', 'tag_closure.id_descendant', 'tag_asset.tagsId')
.innerJoin('tag', 'tag.id', 'tag_closure.id_descendant')
.select((eb) => ['tag.id', eb.fn.count<number>('asset.id').as('count')])
.groupBy('tag.id')
.execute();
const ids = result.filter(({ count }) => count === 0).map(({ id }) => id);
if (ids.length > 0) {
await this.db.deleteFrom('tags').where('id', 'in', ids).execute();
await this.db.deleteFrom('tag').where('id', 'in', ids).execute();
this.logger.log(`Deleted ${ids.length} empty tags`);
}
});

View File

@ -8,13 +8,13 @@ export class TrashRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}
getDeletedIds(): AsyncIterableIterator<{ id: string }> {
return this.db.selectFrom('assets').select(['id']).where('status', '=', AssetStatus.DELETED).stream();
return this.db.selectFrom('asset').select(['id']).where('status', '=', AssetStatus.DELETED).stream();
}
@GenerateSql({ params: [DummyValue.UUID] })
async restore(userId: string): Promise<number> {
const { numUpdatedRows } = await this.db
.updateTable('assets')
.updateTable('asset')
.where('ownerId', '=', userId)
.where('status', '=', AssetStatus.TRASHED)
.set({ status: AssetStatus.ACTIVE, deletedAt: null })
@ -26,7 +26,7 @@ export class TrashRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async empty(userId: string): Promise<number> {
const { numUpdatedRows } = await this.db
.updateTable('assets')
.updateTable('asset')
.where('ownerId', '=', userId)
.where('status', '=', AssetStatus.TRASHED)
.set({ status: AssetStatus.DELETED })
@ -42,7 +42,7 @@ export class TrashRepository {
}
const { numUpdatedRows } = await this.db
.updateTable('assets')
.updateTable('asset')
.where('status', '=', AssetStatus.TRASHED)
.where('id', 'in', ids)
.set({ status: AssetStatus.ACTIVE, deletedAt: null })

View File

@ -34,12 +34,12 @@ export interface UserFindOptions {
withDeleted?: boolean;
}
const withMetadata = (eb: ExpressionBuilder<DB, 'users'>) => {
const withMetadata = (eb: ExpressionBuilder<DB, 'user'>) => {
return jsonArrayFrom(
eb
.selectFrom('user_metadata')
.select(['user_metadata.key', 'user_metadata.value'])
.whereRef('users.id', '=', 'user_metadata.userId'),
.whereRef('user.id', '=', 'user_metadata.userId'),
).as('metadata');
};
@ -52,11 +52,11 @@ export class UserRepository {
options = options || {};
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.select(withMetadata)
.where('users.id', '=', userId)
.$if(!options.withDeleted, (eb) => eb.where('users.deletedAt', 'is', null))
.where('user.id', '=', userId)
.$if(!options.withDeleted, (eb) => eb.where('user.deletedAt', 'is', null))
.executeTakeFirst();
}
@ -71,21 +71,21 @@ export class UserRepository {
@GenerateSql()
getAdmin() {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.select(withMetadata)
.where('users.isAdmin', '=', true)
.where('users.deletedAt', 'is', null)
.where('user.isAdmin', '=', true)
.where('user.deletedAt', 'is', null)
.executeTakeFirst();
}
@GenerateSql()
async hasAdmin(): Promise<boolean> {
const admin = await this.db
.selectFrom('users')
.select('users.id')
.where('users.isAdmin', '=', true)
.where('users.deletedAt', 'is', null)
.selectFrom('user')
.select('user.id')
.where('user.isAdmin', '=', true)
.where('user.deletedAt', 'is', null)
.executeTakeFirst();
return !!admin;
@ -94,59 +94,59 @@ export class UserRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForPinCode(id: string) {
return this.db
.selectFrom('users')
.select(['users.pinCode', 'users.password'])
.where('users.id', '=', id)
.where('users.deletedAt', 'is', null)
.selectFrom('user')
.select(['user.pinCode', 'user.password'])
.where('user.id', '=', id)
.where('user.deletedAt', 'is', null)
.executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.UUID] })
getForChangePassword(id: string) {
return this.db
.selectFrom('users')
.select(['users.id', 'users.password'])
.where('users.id', '=', id)
.where('users.deletedAt', 'is', null)
.selectFrom('user')
.select(['user.id', 'user.password'])
.where('user.id', '=', id)
.where('user.deletedAt', 'is', null)
.executeTakeFirstOrThrow();
}
@GenerateSql({ params: [DummyValue.EMAIL] })
getByEmail(email: string, options?: { withPassword?: boolean }) {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.select(withMetadata)
.$if(!!options?.withPassword, (eb) => eb.select('password'))
.where('email', '=', email)
.where('users.deletedAt', 'is', null)
.where('user.deletedAt', 'is', null)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.STRING] })
getByStorageLabel(storageLabel: string) {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.where('users.storageLabel', '=', storageLabel)
.where('users.deletedAt', 'is', null)
.where('user.storageLabel', '=', storageLabel)
.where('user.deletedAt', 'is', null)
.executeTakeFirst();
}
@GenerateSql({ params: [DummyValue.STRING] })
getByOAuthId(oauthId: string) {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.select(withMetadata)
.where('users.oauthId', '=', oauthId)
.where('users.deletedAt', 'is', null)
.where('user.oauthId', '=', oauthId)
.where('user.deletedAt', 'is', null)
.executeTakeFirst();
}
@GenerateSql({ params: [DateTime.now().minus({ years: 1 })] })
getDeletedAfter(target: DateTime) {
return this.db.selectFrom('users').select(['id']).where('users.deletedAt', '<', target.toJSDate()).execute();
return this.db.selectFrom('user').select(['id']).where('user.deletedAt', '<', target.toJSDate()).execute();
}
@GenerateSql(
@ -155,18 +155,18 @@ export class UserRepository {
)
getList({ id, withDeleted }: UserListFilter = {}) {
return this.db
.selectFrom('users')
.selectFrom('user')
.select(columns.userAdmin)
.select(withMetadata)
.$if(!withDeleted, (eb) => eb.where('users.deletedAt', 'is', null))
.$if(!!id, (eb) => eb.where('users.id', '=', id!))
.$if(!withDeleted, (eb) => eb.where('user.deletedAt', 'is', null))
.$if(!!id, (eb) => eb.where('user.id', '=', id!))
.orderBy('createdAt', 'desc')
.execute();
}
async create(dto: Insertable<UserTable>) {
return this.db
.insertInto('users')
.insertInto('user')
.values(dto)
.returning(columns.userAdmin)
.returning(withMetadata)
@ -175,10 +175,10 @@ export class UserRepository {
update(id: string, dto: Updateable<UserTable>) {
return this.db
.updateTable('users')
.updateTable('user')
.set(dto)
.where('users.id', '=', asUuid(id))
.where('users.deletedAt', 'is', null)
.where('user.id', '=', asUuid(id))
.where('user.deletedAt', 'is', null)
.returning(columns.userAdmin)
.returning(withMetadata)
.executeTakeFirstOrThrow();
@ -186,9 +186,9 @@ export class UserRepository {
restore(id: string) {
return this.db
.updateTable('users')
.updateTable('user')
.set({ status: UserStatus.ACTIVE, deletedAt: null })
.where('users.id', '=', asUuid(id))
.where('user.id', '=', asUuid(id))
.returning(columns.userAdmin)
.returning(withMetadata)
.executeTakeFirstOrThrow();
@ -213,24 +213,24 @@ export class UserRepository {
delete(user: { id: string }, hard?: boolean) {
return hard
? this.db.deleteFrom('users').where('id', '=', user.id).execute()
: this.db.updateTable('users').set({ deletedAt: new Date() }).where('id', '=', user.id).execute();
? this.db.deleteFrom('user').where('id', '=', user.id).execute()
: this.db.updateTable('user').set({ deletedAt: new Date() }).where('id', '=', user.id).execute();
}
@GenerateSql()
getUserStats() {
return this.db
.selectFrom('users')
.leftJoin('assets', (join) => join.onRef('assets.ownerId', '=', 'users.id').on('assets.deletedAt', 'is', null))
.leftJoin('exif', 'exif.assetId', 'assets.id')
.select(['users.id as userId', 'users.name as userName', 'users.quotaSizeInBytes'])
.selectFrom('user')
.leftJoin('asset', (join) => join.onRef('asset.ownerId', '=', 'user.id').on('asset.deletedAt', 'is', null))
.leftJoin('asset_exif', 'asset_exif.assetId', 'asset.id')
.select(['user.id as userId', 'user.name as userName', 'user.quotaSizeInBytes'])
.select((eb) => [
eb.fn
.countAll<number>()
.filterWhere((eb) =>
eb.and([
eb('assets.type', '=', sql.lit(AssetType.IMAGE)),
eb('assets.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
eb('asset.type', '=', sql.lit(AssetType.IMAGE)),
eb('asset.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
]),
)
.as('photos'),
@ -238,20 +238,23 @@ export class UserRepository {
.countAll<number>()
.filterWhere((eb) =>
eb.and([
eb('assets.type', '=', sql.lit(AssetType.VIDEO)),
eb('assets.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
eb('asset.type', '=', sql.lit(AssetType.VIDEO)),
eb('asset.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
]),
)
.as('videos'),
eb.fn
.coalesce(eb.fn.sum<number>('exif.fileSizeInByte').filterWhere('assets.libraryId', 'is', null), eb.lit(0))
.coalesce(
eb.fn.sum<number>('asset_exif.fileSizeInByte').filterWhere('asset.libraryId', 'is', null),
eb.lit(0),
)
.as('usage'),
eb.fn
.coalesce(
eb.fn
.sum<number>('exif.fileSizeInByte')
.sum<number>('asset_exif.fileSizeInByte')
.filterWhere((eb) =>
eb.and([eb('assets.libraryId', 'is', null), eb('assets.type', '=', sql.lit(AssetType.IMAGE))]),
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.IMAGE))]),
),
eb.lit(0),
)
@ -259,45 +262,45 @@ export class UserRepository {
eb.fn
.coalesce(
eb.fn
.sum<number>('exif.fileSizeInByte')
.sum<number>('asset_exif.fileSizeInByte')
.filterWhere((eb) =>
eb.and([eb('assets.libraryId', 'is', null), eb('assets.type', '=', sql.lit(AssetType.VIDEO))]),
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.VIDEO))]),
),
eb.lit(0),
)
.as('usageVideos'),
])
.groupBy('users.id')
.orderBy('users.createdAt', 'asc')
.groupBy('user.id')
.orderBy('user.createdAt', 'asc')
.execute();
}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.NUMBER] })
async updateUsage(id: string, delta: number): Promise<void> {
await this.db
.updateTable('users')
.updateTable('user')
.set({ quotaUsageInBytes: sql`"quotaUsageInBytes" + ${delta}`, updatedAt: new Date() })
.where('id', '=', asUuid(id))
.where('users.deletedAt', 'is', null)
.where('user.deletedAt', 'is', null)
.execute();
}
@GenerateSql({ params: [DummyValue.UUID] })
async syncUsage(id?: string) {
const query = this.db
.updateTable('users')
.updateTable('user')
.set({
quotaUsageInBytes: (eb) =>
eb
.selectFrom('assets')
.leftJoin('exif', 'exif.assetId', 'assets.id')
.select((eb) => eb.fn.coalesce(eb.fn.sum<number>('exif.fileSizeInByte'), eb.lit(0)).as('usage'))
.where('assets.libraryId', 'is', null)
.where('assets.ownerId', '=', eb.ref('users.id')),
.selectFrom('asset')
.leftJoin('asset_exif', 'asset_exif.assetId', 'asset.id')
.select((eb) => eb.fn.coalesce(eb.fn.sum<number>('asset_exif.fileSizeInByte'), eb.lit(0)).as('usage'))
.where('asset.libraryId', 'is', null)
.where('asset.ownerId', '=', eb.ref('user.id')),
updatedAt: new Date(),
})
.where('users.deletedAt', 'is', null)
.$if(id != undefined, (eb) => eb.where('users.id', '=', asUuid(id!)));
.where('user.deletedAt', 'is', null)
.$if(id != undefined, (eb) => eb.where('user.id', '=', asUuid(id!)));
await query.execute();
}

View File

@ -11,8 +11,8 @@ export class ViewRepository {
@GenerateSql({ params: [DummyValue.UUID] })
async getUniqueOriginalPaths(userId: string) {
const results = await this.db
.selectFrom('assets')
.select((eb) => eb.fn<string>('substring', ['assets.originalPath', eb.val('^(.*/)[^/]*$')]).as('directoryPath'))
.selectFrom('asset')
.select((eb) => eb.fn<string>('substring', ['asset.originalPath', eb.val('^(.*/)[^/]*$')]).as('directoryPath'))
.distinct()
.where('ownerId', '=', asUuid(userId))
.where('visibility', '=', AssetVisibility.TIMELINE)
@ -30,8 +30,8 @@ export class ViewRepository {
const normalizedPath = partialPath.replaceAll(/\/$/g, '');
return this.db
.selectFrom('assets')
.selectAll('assets')
.selectFrom('asset')
.selectAll('asset')
.$call(withExif)
.where('ownerId', '=', asUuid(userId))
.where('visibility', '=', AssetVisibility.TIMELINE)
@ -42,7 +42,7 @@ export class ViewRepository {
.where('originalPath', 'like', `%${normalizedPath}/%`)
.where('originalPath', 'not like', `%${normalizedPath}/%/%`)
.orderBy(
(eb) => eb.fn('regexp_replace', ['assets.originalPath', eb.val('.*/(.+)'), eb.val(String.raw`\1`)]),
(eb) => eb.fn('regexp_replace', ['asset.originalPath', eb.val('.*/(.+)'), eb.val(String.raw`\1`)]),
'asc',
)
.execute();

View File

@ -28,7 +28,7 @@ export const album_user_after_insert = registerFunction({
language: 'PLPGSQL',
body: `
BEGIN
UPDATE albums SET "updatedAt" = clock_timestamp(), "updateId" = immich_uuid_v7(clock_timestamp())
UPDATE album SET "updatedAt" = clock_timestamp(), "updateId" = immich_uuid_v7(clock_timestamp())
WHERE "id" IN (SELECT DISTINCT "albumsId" FROM inserted_rows);
RETURN NULL;
END`,
@ -80,83 +80,83 @@ export const ll_to_earth_public = registerFunction({
body: `SELECT public.cube(public.cube(public.cube(public.earth()*cos(radians(latitude))*cos(radians(longitude))),public.earth()*cos(radians(latitude))*sin(radians(longitude))),public.earth()*sin(radians(latitude)))::public.earth`,
});
export const users_delete_audit = registerFunction({
name: 'users_delete_audit',
export const user_delete_audit = registerFunction({
name: 'user_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO users_audit ("userId")
INSERT INTO user_audit ("userId")
SELECT "id"
FROM OLD;
RETURN NULL;
END`,
});
export const partners_delete_audit = registerFunction({
name: 'partners_delete_audit',
export const partner_delete_audit = registerFunction({
name: 'partner_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO partners_audit ("sharedById", "sharedWithId")
INSERT INTO partner_audit ("sharedById", "sharedWithId")
SELECT "sharedById", "sharedWithId"
FROM OLD;
RETURN NULL;
END`,
});
export const assets_delete_audit = registerFunction({
name: 'assets_delete_audit',
export const asset_delete_audit = registerFunction({
name: 'asset_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO assets_audit ("assetId", "ownerId")
INSERT INTO asset_audit ("assetId", "ownerId")
SELECT "id", "ownerId"
FROM OLD;
RETURN NULL;
END`,
});
export const albums_delete_audit = registerFunction({
name: 'albums_delete_audit',
export const album_delete_audit = registerFunction({
name: 'album_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO albums_audit ("albumId", "userId")
INSERT INTO album_audit ("albumId", "userId")
SELECT "id", "ownerId"
FROM OLD;
RETURN NULL;
END`,
});
export const album_assets_delete_audit = registerFunction({
name: 'album_assets_delete_audit',
export const album_asset_delete_audit = registerFunction({
name: 'album_asset_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO album_assets_audit ("albumId", "assetId")
INSERT INTO album_asset_audit ("albumId", "assetId")
SELECT "albumsId", "assetsId" FROM OLD
WHERE "albumsId" IN (SELECT "id" FROM albums WHERE "id" IN (SELECT "albumsId" FROM OLD));
WHERE "albumsId" IN (SELECT "id" FROM album WHERE "id" IN (SELECT "albumsId" FROM OLD));
RETURN NULL;
END`,
});
export const album_users_delete_audit = registerFunction({
name: 'album_users_delete_audit',
export const album_user_delete_audit = registerFunction({
name: 'album_user_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO albums_audit ("albumId", "userId")
INSERT INTO album_audit ("albumId", "userId")
SELECT "albumsId", "usersId"
FROM OLD;
IF pg_trigger_depth() = 1 THEN
INSERT INTO album_users_audit ("albumId", "userId")
INSERT INTO album_user_audit ("albumId", "userId")
SELECT "albumsId", "usersId"
FROM OLD;
END IF;
@ -165,39 +165,39 @@ export const album_users_delete_audit = registerFunction({
END`,
});
export const memories_delete_audit = registerFunction({
name: 'memories_delete_audit',
export const memory_delete_audit = registerFunction({
name: 'memory_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO memories_audit ("memoryId", "userId")
INSERT INTO memory_audit ("memoryId", "userId")
SELECT "id", "ownerId"
FROM OLD;
RETURN NULL;
END`,
});
export const memory_assets_delete_audit = registerFunction({
name: 'memory_assets_delete_audit',
export const memory_asset_delete_audit = registerFunction({
name: 'memory_asset_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO memory_assets_audit ("memoryId", "assetId")
INSERT INTO memory_asset_audit ("memoryId", "assetId")
SELECT "memoriesId", "assetsId" FROM OLD
WHERE "memoriesId" IN (SELECT "id" FROM memories WHERE "id" IN (SELECT "memoriesId" FROM OLD));
WHERE "memoriesId" IN (SELECT "id" FROM memory WHERE "id" IN (SELECT "memoriesId" FROM OLD));
RETURN NULL;
END`,
});
export const stacks_delete_audit = registerFunction({
name: 'stacks_delete_audit',
export const stack_delete_audit = registerFunction({
name: 'stack_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO stacks_audit ("stackId", "userId")
INSERT INTO stack_audit ("stackId", "userId")
SELECT "id", "ownerId"
FROM OLD;
RETURN NULL;

View File

@ -1,20 +1,21 @@
import { asset_face_source_type, asset_visibility_enum, assets_status_enum } from 'src/schema/enums';
import {
album_delete_audit,
album_user_after_insert,
album_users_delete_audit,
albums_delete_audit,
assets_delete_audit,
album_user_delete_audit,
asset_delete_audit,
f_concat_ws,
f_unaccent,
immich_uuid_v7,
ll_to_earth_public,
memories_delete_audit,
memory_assets_delete_audit,
partners_delete_audit,
memory_asset_delete_audit,
memory_delete_audit,
partner_delete_audit,
person_delete_audit,
stacks_delete_audit,
stack_delete_audit,
updated_at,
users_delete_audit,
user_delete_audit,
user_metadata_audit,
} from 'src/schema/functions';
import { ActivityTable } from 'src/schema/tables/activity.table';
import { AlbumAssetAuditTable } from 'src/schema/tables/album-asset-audit.table';
@ -25,12 +26,12 @@ import { AlbumUserTable } from 'src/schema/tables/album-user.table';
import { AlbumTable } from 'src/schema/tables/album.table';
import { ApiKeyTable } from 'src/schema/tables/api-key.table';
import { AssetAuditTable } from 'src/schema/tables/asset-audit.table';
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
import { AssetFileTable } from 'src/schema/tables/asset-files.table';
import { AssetFileTable } from 'src/schema/tables/asset-file.table';
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
import { AssetTable } from 'src/schema/tables/asset.table';
import { AuditTable } from 'src/schema/tables/audit.table';
import { ExifTable } from 'src/schema/tables/exif.table';
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
import { GeodataPlacesTable } from 'src/schema/tables/geodata-places.table';
import { LibraryTable } from 'src/schema/tables/library.table';
@ -81,7 +82,7 @@ export class ImmichDatabase {
AssetTable,
AssetFileTable,
AuditTable,
ExifTable,
AssetExifTable,
FaceSearchTable,
GeodataPlacesTable,
LibraryTable,
@ -120,17 +121,17 @@ export class ImmichDatabase {
f_concat_ws,
f_unaccent,
ll_to_earth_public,
users_delete_audit,
partners_delete_audit,
assets_delete_audit,
albums_delete_audit,
user_delete_audit,
partner_delete_audit,
asset_delete_audit,
album_delete_audit,
album_user_after_insert,
album_users_delete_audit,
memories_delete_audit,
memory_assets_delete_audit,
stacks_delete_audit,
album_user_delete_audit,
memory_delete_audit,
memory_asset_delete_audit,
stack_delete_audit,
person_delete_audit,
users_delete_audit,
user_metadata_audit,
];
enum = [assets_status_enum, asset_face_source_type, asset_visibility_enum];
@ -144,49 +145,71 @@ export interface Migrations {
export interface DB {
activity: ActivityTable;
albums: AlbumTable;
albums_audit: AlbumAuditTable;
albums_assets_assets: AlbumAssetTable;
album_assets_audit: AlbumAssetAuditTable;
albums_shared_users_users: AlbumUserTable;
album_users_audit: AlbumUserAuditTable;
api_keys: ApiKeyTable;
asset_faces: AssetFaceTable;
asset_files: AssetFileTable;
album: AlbumTable;
album_audit: AlbumAuditTable;
album_asset: AlbumAssetTable;
album_asset_audit: AlbumAssetAuditTable;
album_user: AlbumUserTable;
album_user_audit: AlbumUserAuditTable;
api_key: ApiKeyTable;
asset: AssetTable;
asset_exif: AssetExifTable;
asset_face: AssetFaceTable;
asset_file: AssetFileTable;
asset_job_status: AssetJobStatusTable;
asset_stack: StackTable;
assets: AssetTable;
assets_audit: AssetAuditTable;
asset_audit: AssetAuditTable;
audit: AuditTable;
exif: ExifTable;
face_search: FaceSearchTable;
geodata_places: GeodataPlacesTable;
libraries: LibraryTable;
memories: MemoryTable;
memories_audit: MemoryAuditTable;
memories_assets_assets: MemoryAssetTable;
memory_assets_audit: MemoryAssetAuditTable;
library: LibraryTable;
memory: MemoryTable;
memory_audit: MemoryAuditTable;
memory_asset: MemoryAssetTable;
memory_asset_audit: MemoryAssetAuditTable;
migrations: Migrations;
notifications: NotificationTable;
notification: NotificationTable;
move_history: MoveTable;
naturalearth_countries: NaturalEarthCountriesTable;
partners_audit: PartnerAuditTable;
partners: PartnerTable;
partner: PartnerTable;
partner_audit: PartnerAuditTable;
person: PersonTable;
person_audit: PersonAuditTable;
sessions: SessionTable;
session_sync_checkpoints: SessionSyncCheckpointTable;
shared_link__asset: SharedLinkAssetTable;
shared_links: SharedLinkTable;
session: SessionTable;
session_sync_checkpoint: SessionSyncCheckpointTable;
shared_link: SharedLinkTable;
shared_link_asset: SharedLinkAssetTable;
smart_search: SmartSearchTable;
stacks_audit: StackAuditTable;
stack: StackTable;
stack_audit: StackAuditTable;
system_metadata: SystemMetadataTable;
tag: TagTable;
tag_asset: TagAssetTable;
tags: TagTable;
tags_closure: TagClosureTable;
tag_closure: TagClosureTable;
user: UserTable;
user_audit: UserAuditTable;
user_metadata: UserMetadataTable;
user_metadata_audit: UserMetadataAuditTable;
users: UserTable;
users_audit: UserAuditTable;
version_history: VersionHistoryTable;
}

File diff suppressed because it is too large Load Diff

View File

@ -18,19 +18,18 @@ import {
} from 'src/sql-tools';
@Table('activity')
@UpdatedAtTrigger('activity_updated_at')
@UpdatedAtTrigger('activity_updatedAt')
@Index({
name: 'IDX_activity_like',
name: 'activity_like_idx',
columns: ['assetId', 'userId', 'albumId'],
unique: true,
where: '("isLiked" = true)',
})
@Check({
name: 'CHK_2ab1e70f113f450eb40c1e3ec8',
expression: `("comment" IS NULL AND "isLiked" = true) OR ("comment" IS NOT NULL AND "isLiked" = false)`,
name: 'activity_like_check',
expression: `(comment IS NULL AND "isLiked" = true) OR (comment IS NOT NULL AND "isLiked" = false)`,
})
@ForeignKeyConstraint({
name: 'fk_activity_album_asset_composite',
columns: ['albumId', 'assetId'],
referenceTable: () => AlbumAssetTable,
referenceColumns: ['albumsId', 'assetsId'],
@ -62,6 +61,6 @@ export class ActivityTable {
@Column({ type: 'boolean', default: false })
isLiked!: Generated<boolean>;
@UpdateIdColumn({ indexName: 'IDX_activity_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -2,22 +2,20 @@ import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { AlbumTable } from 'src/schema/tables/album.table';
import { Column, CreateDateColumn, ForeignKeyColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('album_assets_audit')
@Table('album_asset_audit')
export class AlbumAssetAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@ForeignKeyColumn(() => AlbumTable, {
type: 'uuid',
indexName: 'IDX_album_assets_audit_album_id',
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
albumId!: string;
@Column({ type: 'uuid', indexName: 'IDX_album_assets_audit_asset_id' })
@Column({ type: 'uuid', index: true })
assetId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_album_assets_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,5 +1,5 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { album_assets_delete_audit } from 'src/schema/functions';
import { album_asset_delete_audit } from 'src/schema/functions';
import { AlbumTable } from 'src/schema/tables/album.table';
import { AssetTable } from 'src/schema/tables/asset.table';
import {
@ -12,11 +12,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'albums_assets_assets', primaryConstraintName: 'PK_c67bc36fa845fb7b18e0e398180' })
@UpdatedAtTrigger('album_assets_updated_at')
@Table({ name: 'album_asset' })
@UpdatedAtTrigger('album_asset_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: album_assets_delete_audit,
function: album_asset_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() <= 1',
})
@ -33,6 +33,6 @@ export class AlbumAssetTable {
@UpdateDateColumn()
updatedAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_album_assets_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -1,17 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('albums_audit')
@Table('album_audit')
export class AlbumAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_albums_audit_album_id' })
@Column({ type: 'uuid', index: true })
albumId!: string;
@Column({ type: 'uuid', indexName: 'IDX_albums_audit_user_id' })
@Column({ type: 'uuid', index: true })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_albums_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,17 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('album_users_audit')
@Table('album_user_audit')
export class AlbumUserAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_album_users_audit_album_id' })
@Column({ type: 'uuid', index: true })
albumId!: string;
@Column({ type: 'uuid', indexName: 'IDX_album_users_audit_user_id' })
@Column({ type: 'uuid', index: true })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_album_users_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,6 +1,6 @@
import { CreateIdColumn, UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AlbumUserRole } from 'src/enum';
import { album_user_after_insert, album_users_delete_audit } from 'src/schema/functions';
import { album_user_after_insert, album_user_delete_audit } from 'src/schema/functions';
import { AlbumTable } from 'src/schema/tables/album.table';
import { UserTable } from 'src/schema/tables/user.table';
import {
@ -10,17 +10,14 @@ import {
CreateDateColumn,
ForeignKeyColumn,
Generated,
Index,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'albums_shared_users_users', primaryConstraintName: 'PK_7df55657e0b2e8b626330a0ebc8' })
@Table({ name: 'album_user' })
// Pre-existing indices from original album <--> user ManyToMany mapping
@Index({ name: 'IDX_427c350ad49bd3935a50baab73', columns: ['albumsId'] })
@Index({ name: 'IDX_f48513bf9bccefd6ff3ad30bd0', columns: ['usersId'] })
@UpdatedAtTrigger('album_users_updated_at')
@UpdatedAtTrigger('album_user_updatedAt')
@AfterInsertTrigger({
name: 'album_user_after_insert',
scope: 'statement',
@ -29,7 +26,7 @@ import {
})
@AfterDeleteTrigger({
scope: 'statement',
function: album_users_delete_audit,
function: album_user_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() <= 1',
})
@ -53,13 +50,13 @@ export class AlbumUserTable {
@Column({ type: 'character varying', default: AlbumUserRole.EDITOR })
role!: Generated<AlbumUserRole>;
@CreateIdColumn({ indexName: 'IDX_album_users_create_id' })
@CreateIdColumn({ index: true })
createId!: Generated<string>;
@CreateDateColumn()
createdAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_album_users_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@UpdateDateColumn()

View File

@ -1,6 +1,6 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AssetOrder } from 'src/enum';
import { albums_delete_audit } from 'src/schema/functions';
import { album_delete_audit } from 'src/schema/functions';
import { AssetTable } from 'src/schema/tables/asset.table';
import { UserTable } from 'src/schema/tables/user.table';
import {
@ -16,11 +16,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'albums', primaryConstraintName: 'PK_7f71c7b5bc7c87b8f94c9a93a00' })
@UpdatedAtTrigger('albums_updated_at')
@Table({ name: 'album' })
@UpdatedAtTrigger('album_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: albums_delete_audit,
function: album_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@ -60,6 +60,6 @@ export class AlbumTable {
@Column({ default: AssetOrder.DESC })
order!: Generated<AssetOrder>;
@UpdateIdColumn({ indexName: 'IDX_albums_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -12,8 +12,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('api_keys')
@UpdatedAtTrigger('api_keys_updated_at')
@Table('api_key')
@UpdatedAtTrigger('api_key_updatedAt')
export class ApiKeyTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -36,6 +36,6 @@ export class ApiKeyTable {
@Column({ array: true, type: 'character varying' })
permissions!: Permission[];
@UpdateIdColumn({ indexName: 'IDX_api_keys_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -1,17 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('assets_audit')
@Table('asset_audit')
export class AssetAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_assets_audit_asset_id' })
@Column({ type: 'uuid', index: true })
assetId!: string;
@Column({ type: 'uuid', indexName: 'IDX_assets_audit_owner_id' })
@Column({ type: 'uuid', index: true })
ownerId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_assets_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -2,9 +2,9 @@ import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, Generated, Int8, Table, Timestamp, UpdateDateColumn } from 'src/sql-tools';
@Table('exif')
@UpdatedAtTrigger('asset_exif_updated_at')
export class ExifTable {
@Table('asset_exif')
@UpdatedAtTrigger('asset_exif_updatedAt')
export class AssetExifTable {
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', primary: true })
assetId!: string;
@ -50,7 +50,7 @@ export class ExifTable {
@Column({ type: 'double precision', nullable: true })
longitude!: number | null;
@Column({ type: 'character varying', nullable: true, indexName: 'exif_city' })
@Column({ type: 'character varying', nullable: true, index: true })
city!: string | null;
@Column({ type: 'character varying', nullable: true })
@ -68,7 +68,7 @@ export class ExifTable {
@Column({ type: 'character varying', nullable: true })
exposureTime!: string | null;
@Column({ type: 'character varying', nullable: true, indexName: 'IDX_live_photo_cid' })
@Column({ type: 'character varying', nullable: true, index: true })
livePhotoCID!: string | null;
@Column({ type: 'character varying', nullable: true })
@ -86,7 +86,7 @@ export class ExifTable {
@Column({ type: 'integer', nullable: true })
bitsPerSample!: number | null;
@Column({ type: 'character varying', nullable: true, indexName: 'IDX_auto_stack_id' })
@Column({ type: 'character varying', nullable: true, index: true })
autoStackId!: string | null;
@Column({ type: 'integer', nullable: true })
@ -95,6 +95,6 @@ export class ExifTable {
@UpdateDateColumn({ default: () => 'clock_timestamp()' })
updatedAt!: Generated<Date>;
@UpdateIdColumn({ indexName: 'IDX_asset_exif_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -13,8 +13,9 @@ import {
Timestamp,
} from 'src/sql-tools';
@Table({ name: 'asset_faces' })
@Index({ name: 'IDX_asset_faces_assetId_personId', columns: ['assetId', 'personId'] })
@Table({ name: 'asset_face' })
// schemaFromDatabase does not preserve column order
@Index({ name: 'asset_face_assetId_personId_idx', columns: ['assetId', 'personId'] })
@Index({ columns: ['personId', 'assetId'] })
export class AssetFaceTable {
@PrimaryGeneratedColumn()

View File

@ -13,18 +13,14 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('asset_files')
@Unique({ name: 'UQ_assetId_type', columns: ['assetId', 'type'] })
@UpdatedAtTrigger('asset_files_updated_at')
@Table('asset_file')
@Unique({ columns: ['assetId', 'type'] })
@UpdatedAtTrigger('asset_file_updatedAt')
export class AssetFileTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ForeignKeyColumn(() => AssetTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
indexName: 'IDX_asset_files_assetId',
})
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
assetId!: string;
@CreateDateColumn()
@ -39,6 +35,6 @@ export class AssetFileTable {
@Column()
path!: string;
@UpdateIdColumn({ indexName: 'IDX_asset_files_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -1,7 +1,7 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AssetStatus, AssetType, AssetVisibility } from 'src/enum';
import { asset_visibility_enum, assets_status_enum } from 'src/schema/enums';
import { assets_delete_audit } from 'src/schema/functions';
import { asset_delete_audit } from 'src/schema/functions';
import { LibraryTable } from 'src/schema/tables/library.table';
import { StackTable } from 'src/schema/tables/stack.table';
import { UserTable } from 'src/schema/tables/user.table';
@ -20,11 +20,11 @@ import {
} from 'src/sql-tools';
import { ASSET_CHECKSUM_CONSTRAINT } from 'src/utils/database';
@Table('assets')
@UpdatedAtTrigger('assets_updated_at')
@Table('asset')
@UpdatedAtTrigger('asset_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: assets_delete_audit,
function: asset_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@ -36,23 +36,22 @@ import { ASSET_CHECKSUM_CONSTRAINT } from 'src/utils/database';
where: '("libraryId" IS NULL)',
})
@Index({
name: 'UQ_assets_owner_library_checksum' + '',
columns: ['ownerId', 'libraryId', 'checksum'],
unique: true,
where: '("libraryId" IS NOT NULL)',
})
@Index({
name: 'idx_local_date_time',
name: 'asset_localDateTime_idx',
expression: `(("localDateTime" at time zone 'UTC')::date)`,
})
@Index({
name: 'idx_local_date_time_month',
name: 'asset_localDateTime_month_idx',
expression: `(date_trunc('MONTH'::text, ("localDateTime" AT TIME ZONE 'UTC'::text)) AT TIME ZONE 'UTC'::text)`,
})
@Index({ name: 'IDX_originalPath_libraryId', columns: ['originalPath', 'libraryId'] })
@Index({ name: 'IDX_asset_id_stackId', columns: ['id', 'stackId'] })
@Index({ columns: ['originalPath', 'libraryId'] })
@Index({ columns: ['id', 'stackId'] })
@Index({
name: 'idx_originalfilename_trigram',
name: 'asset_originalFilename_trigram_idx',
using: 'gin',
expression: 'f_unaccent("originalFileName") gin_trgm_ops',
})
@ -76,7 +75,7 @@ export class AssetTable {
@Column()
originalPath!: string;
@Column({ type: 'timestamp with time zone', indexName: 'idx_asset_file_created_at' })
@Column({ type: 'timestamp with time zone', index: true })
fileCreatedAt!: Timestamp;
@Column({ type: 'timestamp with time zone' })
@ -130,13 +129,13 @@ export class AssetTable {
@ForeignKeyColumn(() => StackTable, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
stackId!: string | null;
@Column({ type: 'uuid', nullable: true, indexName: 'IDX_assets_duplicateId' })
@Column({ type: 'uuid', nullable: true, index: true })
duplicateId!: string | null;
@Column({ enum: assets_status_enum, default: AssetStatus.ACTIVE })
status!: Generated<AssetStatus>;
@UpdateIdColumn({ indexName: 'IDX_assets_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@Column({ enum: asset_visibility_enum, default: AssetVisibility.TIMELINE })

View File

@ -2,7 +2,7 @@ import { DatabaseAction, EntityType } from 'src/enum';
import { Column, CreateDateColumn, Generated, Index, PrimaryColumn, Table, Timestamp } from 'src/sql-tools';
@Table('audit')
@Index({ name: 'IDX_ownerId_createdAt', columns: ['ownerId', 'createdAt'] })
@Index({ columns: ['ownerId', 'createdAt'] })
export class AuditTable {
@PrimaryColumn({ type: 'serial', synchronize: false })
id!: Generated<number>;

View File

@ -1,7 +1,7 @@
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
@Table({ name: 'face_search', primaryConstraintName: 'face_search_pkey' })
@Table({ name: 'face_search' })
@Index({
name: 'face_index',
using: 'hnsw',
@ -9,11 +9,7 @@ import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
with: 'ef_construction = 300, m = 16',
})
export class FaceSearchTable {
@ForeignKeyColumn(() => AssetFaceTable, {
onDelete: 'CASCADE',
primary: true,
constraintName: 'face_search_faceId_fkey',
})
@ForeignKeyColumn(() => AssetFaceTable, { onDelete: 'CASCADE', primary: true })
faceId!: string;
@Column({ type: 'vector', length: 512, synchronize: false })

View File

@ -12,8 +12,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('libraries')
@UpdatedAtTrigger('libraries_updated_at')
@Table('library')
@UpdatedAtTrigger('library_updatedAt')
export class LibraryTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -42,6 +42,6 @@ export class LibraryTable {
@Column({ type: 'timestamp with time zone', nullable: true })
refreshedAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_libraries_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -2,22 +2,17 @@ import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { MemoryTable } from 'src/schema/tables/memory.table';
import { Column, CreateDateColumn, ForeignKeyColumn, Table } from 'src/sql-tools';
@Table('memory_assets_audit')
@Table('memory_asset_audit')
export class MemoryAssetAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
@ForeignKeyColumn(() => MemoryTable, {
type: 'uuid',
indexName: 'IDX_memory_assets_audit_memory_id',
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
@ForeignKeyColumn(() => MemoryTable, { type: 'uuid', onDelete: 'CASCADE', onUpdate: 'CASCADE' })
memoryId!: string;
@Column({ type: 'uuid', indexName: 'IDX_memory_assets_audit_asset_id' })
@Column({ type: 'uuid', index: true })
assetId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_memory_assets_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Date;
}

View File

@ -1,5 +1,5 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { memory_assets_delete_audit } from 'src/schema/functions';
import { memory_asset_delete_audit } from 'src/schema/functions';
import { AssetTable } from 'src/schema/tables/asset.table';
import { MemoryTable } from 'src/schema/tables/memory.table';
import {
@ -12,11 +12,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('memories_assets_assets')
@UpdatedAtTrigger('memory_assets_updated_at')
@Table('memory_asset')
@UpdatedAtTrigger('memory_asset_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: memory_assets_delete_audit,
function: memory_asset_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() <= 1',
})
@ -33,6 +33,6 @@ export class MemoryAssetTable {
@UpdateDateColumn()
updatedAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_memory_assets_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -1,17 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('memories_audit')
@Table('memory_audit')
export class MemoryAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_memories_audit_memory_id' })
@Column({ type: 'uuid', index: true })
memoryId!: string;
@Column({ type: 'uuid', indexName: 'IDX_memories_audit_user_id' })
@Column({ type: 'uuid', index: true })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_memories_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,6 +1,6 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { MemoryType } from 'src/enum';
import { memories_delete_audit } from 'src/schema/functions';
import { memory_delete_audit } from 'src/schema/functions';
import { UserTable } from 'src/schema/tables/user.table';
import {
AfterDeleteTrigger,
@ -15,11 +15,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('memories')
@UpdatedAtTrigger('memories_updated_at')
@Table('memory')
@UpdatedAtTrigger('memory_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: memories_delete_audit,
function: memory_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@ -63,6 +63,6 @@ export class MemoryTable {
@Column({ type: 'timestamp with time zone', nullable: true })
hideAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_memories_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -13,8 +13,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('notifications')
@UpdatedAtTrigger('notifications_updated_at')
@Table('notification')
@UpdatedAtTrigger('notification_updatedAt')
export class NotificationTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -28,7 +28,7 @@ export class NotificationTable {
@DeleteDateColumn()
deletedAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_notifications_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })

View File

@ -1,17 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('partners_audit')
@Table('partner_audit')
export class PartnerAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_partners_audit_shared_by_id' })
@Column({ type: 'uuid', index: true })
sharedById!: string;
@Column({ type: 'uuid', indexName: 'IDX_partners_audit_shared_with_id' })
@Column({ type: 'uuid', index: true })
sharedWithId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_partners_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,5 +1,5 @@
import { CreateIdColumn, UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { partners_delete_audit } from 'src/schema/functions';
import { partner_delete_audit } from 'src/schema/functions';
import { UserTable } from 'src/schema/tables/user.table';
import {
AfterDeleteTrigger,
@ -12,11 +12,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('partners')
@UpdatedAtTrigger('partners_updated_at')
@Table('partner')
@UpdatedAtTrigger('partner_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: partners_delete_audit,
function: partner_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@ -35,7 +35,7 @@ export class PartnerTable {
@CreateDateColumn()
createdAt!: Generated<Timestamp>;
@CreateIdColumn({ indexName: 'IDX_partners_create_id' })
@CreateIdColumn({ index: true })
createId!: Generated<string>;
@UpdateDateColumn()
@ -44,6 +44,6 @@ export class PartnerTable {
@Column({ type: 'boolean', default: false })
inTimeline!: Generated<boolean>;
@UpdateIdColumn({ indexName: 'IDX_partners_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -6,12 +6,12 @@ export class PersonAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_person_audit_person_id' })
@Column({ type: 'uuid', index: true })
personId!: string;
@Column({ type: 'uuid', indexName: 'IDX_person_audit_owner_id' })
@Column({ type: 'uuid', index: true })
ownerId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_person_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -16,14 +16,14 @@ import {
} from 'src/sql-tools';
@Table('person')
@UpdatedAtTrigger('person_updated_at')
@UpdatedAtTrigger('person_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: person_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@Check({ name: 'CHK_b0f82b0ed662bfc24fbb58bb45', expression: `"birthDate" <= CURRENT_DATE` })
@Check({ name: 'person_birthDate_chk', expression: `"birthDate" <= CURRENT_DATE` })
export class PersonTable {
@PrimaryGeneratedColumn('uuid')
id!: Generated<string>;
@ -58,6 +58,6 @@ export class PersonTable {
@Column({ type: 'character varying', nullable: true, default: null })
color!: string | null;
@UpdateIdColumn({ indexName: 'IDX_person_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -11,8 +11,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'sessions', primaryConstraintName: 'PK_48cb6b5c20faa63157b3c1baf7f' })
@UpdatedAtTrigger('sessions_updated_at')
@Table({ name: 'session' })
@UpdatedAtTrigger('session_updatedAt')
export class SessionTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -42,7 +42,7 @@ export class SessionTable {
@Column({ default: '' })
deviceOS!: Generated<string>;
@UpdateIdColumn({ indexName: 'IDX_sessions_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@Column({ type: 'boolean', default: false })

View File

@ -2,7 +2,7 @@ import { AssetTable } from 'src/schema/tables/asset.table';
import { SharedLinkTable } from 'src/schema/tables/shared-link.table';
import { ForeignKeyColumn, Table } from 'src/sql-tools';
@Table('shared_link__asset')
@Table('shared_link_asset')
export class SharedLinkAssetTable {
@ForeignKeyColumn(() => AssetTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
assetsId!: string;

View File

@ -9,11 +9,9 @@ import {
PrimaryGeneratedColumn,
Table,
Timestamp,
Unique,
} from 'src/sql-tools';
@Table('shared_links')
@Unique({ name: 'UQ_sharedlink_key', columns: ['key'] })
@Table('shared_link')
export class SharedLinkTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -24,7 +22,7 @@ export class SharedLinkTable {
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
userId!: string;
@Column({ type: 'bytea', indexName: 'IDX_sharedlink_key' })
@Column({ type: 'bytea', index: true, unique: true })
key!: Buffer; // use to access the individual asset
@Column()
@ -39,12 +37,7 @@ export class SharedLinkTable {
@Column({ type: 'boolean', default: false })
allowUpload!: boolean;
@ForeignKeyColumn(() => AlbumTable, {
nullable: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
indexName: 'IDX_sharedlink_albumId',
})
@ForeignKeyColumn(() => AlbumTable, { nullable: true, onDelete: 'CASCADE', onUpdate: 'CASCADE' })
albumId!: string | null;
@Column({ type: 'boolean', default: true })

View File

@ -1,7 +1,7 @@
import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
@Table({ name: 'smart_search', primaryConstraintName: 'smart_search_pkey' })
@Table({ name: 'smart_search' })
@Index({
name: 'clip_index',
using: 'hnsw',
@ -10,11 +10,7 @@ import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
synchronize: false,
})
export class SmartSearchTable {
@ForeignKeyColumn(() => AssetTable, {
onDelete: 'CASCADE',
primary: true,
constraintName: 'smart_search_assetId_fkey',
})
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', primary: true })
assetId!: string;
@Column({ type: 'vector', length: 512, storage: 'external', synchronize: false })

View File

@ -1,7 +1,7 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('stacks_audit')
@Table('stack_audit')
export class StackAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@ -12,6 +12,6 @@ export class StackAuditTable {
@Column({ type: 'uuid' })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_stacks_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,5 +1,5 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { stacks_delete_audit } from 'src/schema/functions';
import { stack_delete_audit } from 'src/schema/functions';
import { AssetTable } from 'src/schema/tables/asset.table';
import { UserTable } from 'src/schema/tables/user.table';
import {
@ -13,11 +13,11 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('asset_stack')
@UpdatedAtTrigger('stacks_updated_at')
@Table('stack')
@UpdatedAtTrigger('stack_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: stacks_delete_audit,
function: stack_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@ -35,11 +35,7 @@ export class StackTable {
updateId!: Generated<string>;
//TODO: Add constraint to ensure primary asset exists in the assets array
@ForeignKeyColumn(() => AssetTable, {
nullable: false,
unique: true,
uniqueConstraintName: 'REL_91704e101438fd0653f582426d',
})
@ForeignKeyColumn(() => AssetTable, { nullable: false, unique: true })
primaryAssetId!: string;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })

View File

@ -12,8 +12,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('session_sync_checkpoints')
@UpdatedAtTrigger('session_sync_checkpoints_updated_at')
@Table('session_sync_checkpoint')
@UpdatedAtTrigger('session_sync_checkpoint_updatedAt')
export class SessionSyncCheckpointTable {
@ForeignKeyColumn(() => SessionTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', primary: true })
sessionId!: string;
@ -30,6 +30,6 @@ export class SessionSyncCheckpointTable {
@Column()
ack!: string;
@UpdateIdColumn({ indexName: 'IDX_session_sync_checkpoints_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -2,7 +2,7 @@ import { AssetTable } from 'src/schema/tables/asset.table';
import { TagTable } from 'src/schema/tables/tag.table';
import { ForeignKeyColumn, Index, Table } from 'src/sql-tools';
@Index({ name: 'IDX_tag_asset_assetsId_tagsId', columns: ['assetsId', 'tagsId'] })
@Index({ columns: ['assetsId', 'tagsId'] })
@Table('tag_asset')
export class TagAssetTable {
@ForeignKeyColumn(() => AssetTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true, index: true })

View File

@ -1,7 +1,7 @@
import { TagTable } from 'src/schema/tables/tag.table';
import { ForeignKeyColumn, Table } from 'src/sql-tools';
@Table('tags_closure')
@Table('tag_closure')
export class TagClosureTable {
@ForeignKeyColumn(() => TagTable, { primary: true, onDelete: 'CASCADE', onUpdate: 'NO ACTION', index: true })
id_ancestor!: string;

View File

@ -12,8 +12,8 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('tags')
@UpdatedAtTrigger('tags_updated_at')
@Table('tag')
@UpdatedAtTrigger('tag_updatedAt')
@Unique({ columns: ['userId', 'value'] })
export class TagTable {
@PrimaryGeneratedColumn()
@ -42,6 +42,6 @@ export class TagTable {
@ForeignKeyColumn(() => TagTable, { nullable: true, onDelete: 'CASCADE' })
parentId!: string | null;
@UpdateIdColumn({ indexName: 'IDX_tags_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -1,7 +1,7 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('users_audit')
@Table('user_audit')
export class UserAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@ -9,6 +9,6 @@ export class UserAuditTable {
@Column({ type: 'uuid' })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_users_audit_deleted_at' })
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}

View File

@ -1,7 +1,7 @@
import { ColumnType } from 'kysely';
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { UserAvatarColor, UserStatus } from 'src/enum';
import { users_delete_audit } from 'src/schema/functions';
import { user_delete_audit } from 'src/schema/functions';
import {
AfterDeleteTrigger,
Column,
@ -15,15 +15,15 @@ import {
UpdateDateColumn,
} from 'src/sql-tools';
@Table('users')
@UpdatedAtTrigger('users_updated_at')
@Table('user')
@UpdatedAtTrigger('user_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: users_delete_audit,
function: user_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0',
})
@Index({ name: 'IDX_users_updated_at_asc_id_asc', columns: ['updatedAt', 'id'] })
@Index({ columns: ['updatedAt', 'id'] })
export class UserTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ -79,6 +79,6 @@ export class UserTable {
@Column({ type: 'timestamp with time zone', default: () => 'now()' })
profileChangedAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_users_update_id' })
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}

View File

@ -24,8 +24,8 @@ import {
import { ArgOf } from 'src/repositories/event.repository';
import { ReverseGeocodeResult } from 'src/repositories/map.repository';
import { ImmichTags } from 'src/repositories/metadata.repository';
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
import { ExifTable } from 'src/schema/tables/exif.table';
import { PersonTable } from 'src/schema/tables/person.table';
import { BaseService } from 'src/services/base.service';
import { JobItem, JobOf } from 'src/types';
@ -164,7 +164,7 @@ export class MetadataService extends BaseService {
private async linkLivePhotos(
asset: { id: string; type: AssetType; ownerId: string; libraryId: string | null },
exifInfo: Insertable<ExifTable>,
exifInfo: Insertable<AssetExifTable>,
): Promise<void> {
if (!exifInfo.livePhotoCID) {
return;
@ -242,7 +242,7 @@ export class MetadataService extends BaseService {
}
}
const exifData: Insertable<ExifTable> = {
const exifData: Insertable<AssetExifTable> = {
assetId: asset.id,
// dates

View File

@ -31,7 +31,8 @@ export const compareConstraints: Comparer<DatabaseConstraint> = {
}
case ConstraintType.CHECK: {
return asRenameKey([constraint.type, constraint.tableName, constraint.expression]);
const expression = constraint.expression.replaceAll('(', '').replaceAll(')', '');
return asRenameKey([constraint.type, constraint.tableName, expression]);
}
}
},

View File

@ -7,7 +7,7 @@ export const compareIndexes: Comparer<DatabaseIndex> = {
return index.override.value.sql.replace(index.name, 'INDEX_NAME');
}
return asRenameKey([index.tableName, ...(index.columnNames || []).toSorted(), index.unique]);
return asRenameKey([index.tableName, ...(index.columnNames || []), index.unique]);
},
onRename: (source, target) => [
{

View File

@ -30,28 +30,35 @@ export const schemaDiff = (source: DatabaseSchema, target: DatabaseSchema, optio
type SchemaName = SchemaDiff['type'];
const itemMap: Record<SchemaName, SchemaDiff[]> = {
EnumCreate: [],
EnumDrop: [],
ExtensionCreate: [],
ExtensionDrop: [],
FunctionCreate: [],
FunctionDrop: [],
TableCreate: [],
TableDrop: [],
ColumnAdd: [],
ColumnAlter: [],
ColumnRename: [],
ColumnDrop: [],
ConstraintAdd: [],
ConstraintDrop: [],
ConstraintRename: [],
IndexCreate: [],
IndexRename: [],
IndexDrop: [],
TriggerCreate: [],
TriggerDrop: [],
ExtensionDrop: [],
ExtensionCreate: [],
ParameterSet: [],
ParameterReset: [],
FunctionDrop: [],
FunctionCreate: [],
EnumDrop: [],
EnumCreate: [],
TriggerDrop: [],
ConstraintDrop: [],
TableDrop: [],
ColumnDrop: [],
ColumnAdd: [],
ColumnAlter: [],
TableCreate: [],
ConstraintAdd: [],
TriggerCreate: [],
IndexCreate: [],
IndexDrop: [],
OverrideCreate: [],
OverrideUpdate: [],
OverrideDrop: [],

Some files were not shown because too many files have changed in this diff Show More