diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a2f946f02..2505aa185 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -209,7 +209,7 @@ jobs:
           exit 1
 
   generated-typeorm-migrations-up-to-date:
-    name: TypeORM Migrations
+    name: TypeORM Checks
     runs-on: ubuntu-latest
     services:
       postgres:
@@ -236,7 +236,7 @@ jobs:
       - name: Install server dependencies
         run: npm ci
 
-      - name: Build the
+      - name: Build the app
         run: npm run build
 
       - name: Run existing migrations
@@ -252,13 +252,30 @@ jobs:
         with:
           files: |
             server/src/infra/migrations/
-      - name: Verify files have not changed
+      - name: Verify migration files have not changed
         if: steps.verify-changed-files.outputs.files_changed == 'true'
         run: |
-          echo "ERROR: Generated files not up to date!"
+          echo "ERROR: Generated migration files not up to date!"
           echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
           exit 1
 
+      - name: Run SQL generation
+        run: npm run sql:generate
+
+      - name: Find file changes
+        uses: tj-actions/verify-changed-files@v13.1
+        id: verify-changed-sql-files
+        with:
+          files: |
+            server/src/infra/sql
+
+      - name: Verify SQL files have not changed
+        if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
+        run: |
+          echo "ERROR: Generated SQL files not up to date!"
+          echo "Changed files: ${{ steps.verify-changed-sql-files.outputs.changed_files }}"
+          exit 1
+
   # mobile-integration-tests:
   #   name: Run mobile end-to-end integration tests
   #   runs-on: macos-latest
diff --git a/Makefile b/Makefile
index 7668d4f60..73b922ee8 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,10 @@ prod-scale:
 	docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
 
 api:
-	cd ./server && npm run api:generate
+	npm --prefix server run api:generate
+
+sql:
+	npm --prefix server run sql:generate
 
 attach-server:
 	docker exec -it docker_immich-server_1 sh
diff --git a/server/package-lock.json b/server/package-lock.json
index 19a4851c8..77145427a 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -93,6 +93,7 @@
         "prettier-plugin-organize-imports": "^3.2.3",
         "rimraf": "^5.0.1",
         "source-map-support": "^0.5.21",
+        "sql-formatter": "^14.0.0",
         "supertest": "^6.3.3",
         "testcontainers": "^10.2.1",
         "ts-jest": "^29.1.1",
@@ -5504,6 +5505,12 @@
         "node": ">=8"
       }
     },
+    "node_modules/discontinuous-range": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+      "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
+      "dev": true
+    },
     "node_modules/docker-compose": {
       "version": "0.24.2",
       "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz",
@@ -6740,6 +6747,18 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/get-stdin": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+      "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/get-stream": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -8723,6 +8742,12 @@
         "node": ">=12.0.0"
       }
     },
+    "node_modules/moo": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
+      "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
+      "dev": true
+    },
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -8895,6 +8920,34 @@
         "ncp": "bin/ncp"
       }
     },
+    "node_modules/nearley": {
+      "version": "2.20.1",
+      "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
+      "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
+      "dev": true,
+      "dependencies": {
+        "commander": "^2.19.0",
+        "moo": "^0.5.0",
+        "railroad-diagrams": "^1.0.0",
+        "randexp": "0.4.6"
+      },
+      "bin": {
+        "nearley-railroad": "bin/nearley-railroad.js",
+        "nearley-test": "bin/nearley-test.js",
+        "nearley-unparse": "bin/nearley-unparse.js",
+        "nearleyc": "bin/nearleyc.js"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://nearley.js.org/#give-to-nearley"
+      }
+    },
+    "node_modules/nearley/node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
     "node_modules/negotiator": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -9964,6 +10017,25 @@
       "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
       "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
     },
+    "node_modules/railroad-diagrams": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+      "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+      "dev": true
+    },
+    "node_modules/randexp": {
+      "version": "0.4.6",
+      "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+      "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+      "dev": true,
+      "dependencies": {
+        "discontinuous-range": "1.0.0",
+        "ret": "~0.1.10"
+      },
+      "engines": {
+        "node": ">=0.12"
+      }
+    },
     "node_modules/randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -10222,6 +10294,15 @@
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
       "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
     },
+    "node_modules/ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12"
+      }
+    },
     "node_modules/retry": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
@@ -10806,6 +10887,20 @@
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
       "dev": true
     },
+    "node_modules/sql-formatter": {
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-14.0.0.tgz",
+      "integrity": "sha512-VcHYMRvZqg3RNjjxNB/puT9O1hR5QLXTvgTaBtxXcvmRQwSnH9M+oW2Ti+uFuVVU8HoNlOjU2uKHv8c0FQNsdQ==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1",
+        "get-stdin": "=8.0.0",
+        "nearley": "^2.20.1"
+      },
+      "bin": {
+        "sql-formatter": "bin/sql-formatter-cli.cjs"
+      }
+    },
     "node_modules/ssh-remote-port-forward": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz",
@@ -16768,6 +16863,12 @@
         "path-type": "^4.0.0"
       }
     },
+    "discontinuous-range": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+      "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
+      "dev": true
+    },
     "docker-compose": {
       "version": "0.24.2",
       "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.2.tgz",
@@ -17718,6 +17819,12 @@
       "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
       "dev": true
     },
+    "get-stdin": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+      "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+      "dev": true
+    },
     "get-stream": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -19188,6 +19295,12 @@
       "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==",
       "dev": true
     },
+    "moo": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
+      "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
+      "dev": true
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -19340,6 +19453,26 @@
       "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
       "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="
     },
+    "nearley": {
+      "version": "2.20.1",
+      "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
+      "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.19.0",
+        "moo": "^0.5.0",
+        "railroad-diagrams": "^1.0.0",
+        "randexp": "0.4.6"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+          "dev": true
+        }
+      }
+    },
     "negotiator": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -20107,6 +20240,22 @@
       "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
       "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
     },
+    "railroad-diagrams": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+      "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+      "dev": true
+    },
+    "randexp": {
+      "version": "0.4.6",
+      "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+      "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+      "dev": true,
+      "requires": {
+        "discontinuous-range": "1.0.0",
+        "ret": "~0.1.10"
+      }
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -20313,6 +20462,12 @@
         }
       }
     },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true
+    },
     "retry": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
@@ -20747,6 +20902,17 @@
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
       "dev": true
     },
+    "sql-formatter": {
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-14.0.0.tgz",
+      "integrity": "sha512-VcHYMRvZqg3RNjjxNB/puT9O1hR5QLXTvgTaBtxXcvmRQwSnH9M+oW2Ti+uFuVVU8HoNlOjU2uKHv8c0FQNsdQ==",
+      "dev": true,
+      "requires": {
+        "argparse": "^2.0.1",
+        "get-stdin": "=8.0.0",
+        "nearley": "^2.20.1"
+      }
+    },
     "ssh-remote-port-forward": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz",
diff --git a/server/package.json b/server/package.json
index 142cb92e1..bf424abe8 100644
--- a/server/package.json
+++ b/server/package.json
@@ -36,7 +36,8 @@
     "typeorm:schema:reset": "npm run typeorm:schema:drop && npm run typeorm:migrations:run",
     "api:typescript": "bash ./bin/generate-open-api.sh web",
     "api:dart": "bash ./bin/generate-open-api.sh mobile",
-    "api:generate": "node ./bin/sync-spec-version.js && bash ./bin/generate-open-api.sh"
+    "api:generate": "node ./bin/sync-spec-version.js && bash ./bin/generate-open-api.sh",
+    "sql:generate": "node ./dist/infra/sql-generator/"
   },
   "dependencies": {
     "@babel/runtime": "^7.22.11",
@@ -119,6 +120,7 @@
     "prettier-plugin-organize-imports": "^3.2.3",
     "rimraf": "^5.0.1",
     "source-map-support": "^0.5.21",
+    "sql-formatter": "^14.0.0",
     "supertest": "^6.3.3",
     "testcontainers": "^10.2.1",
     "ts-jest": "^29.1.1",
diff --git a/server/src/infra/infra.module.ts b/server/src/infra/infra.module.ts
index e0d5711d6..6cfaebefc 100644
--- a/server/src/infra/infra.module.ts
+++ b/server/src/infra/infra.module.ts
@@ -36,10 +36,10 @@ import { databaseConfig } from './database.config';
 import { databaseEntities } from './entities';
 import { bullConfig, bullQueues } from './infra.config';
 import {
-  APIKeyRepository,
   AccessRepository,
   ActivityRepository,
   AlbumRepository,
+  ApiKeyRepository,
   AssetRepository,
   AuditRepository,
   CommunicationRepository,
@@ -74,7 +74,7 @@ const providers: Provider[] = [
   { provide: ICryptoRepository, useClass: CryptoRepository },
   { provide: IJobRepository, useClass: JobRepository },
   { provide: ILibraryRepository, useClass: LibraryRepository },
-  { provide: IKeyRepository, useClass: APIKeyRepository },
+  { provide: IKeyRepository, useClass: ApiKeyRepository },
   { provide: IMachineLearningRepository, useClass: MachineLearningRepository },
   { provide: IMetadataRepository, useClass: MetadataRepository },
   { provide: IMoveRepository, useClass: MoveRepository },
diff --git a/server/src/infra/infra.util.ts b/server/src/infra/infra.util.ts
new file mode 100644
index 000000000..8b2cd7efa
--- /dev/null
+++ b/server/src/infra/infra.util.ts
@@ -0,0 +1,20 @@
+import { SetMetadata } from '@nestjs/common';
+
+export const GENERATE_SQL_KEY = 'generate-sql-key';
+
+export interface GenerateSqlQueries {
+  name?: string;
+  params?: any[];
+}
+
+/** Decorator to enable versioning/tracking of generated Sql */
+export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options);
+
+export const DummyValue = {
+  UUID: '00000000-0000-4000-a000-000000000000',
+  PAGINATION: { take: 10, skip: 0 },
+  EMAIL: 'user@immich.app',
+  STRING: 'abcdefghi',
+  BUFFER: Buffer.from('abcdefghi'),
+  DATE: new Date(),
+};
diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/infra/repositories/activity.repository.ts
index 25fd5fa7a..319c9c647 100644
--- a/server/src/infra/repositories/activity.repository.ts
+++ b/server/src/infra/repositories/activity.repository.ts
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { IsNull, Repository } from 'typeorm';
 import { ActivityEntity } from '../entities/activity.entity';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 export interface ActivitySearch {
   albumId?: string;
@@ -15,6 +16,7 @@ export interface ActivitySearch {
 export class ActivityRepository implements IActivityRepository {
   constructor(@InjectRepository(ActivityEntity) private repository: Repository<ActivityEntity>) {}
 
+  @GenerateSql({ params: [{ albumId: DummyValue.UUID }] })
   search(options: ActivitySearch): Promise<ActivityEntity[]> {
     const { userId, assetId, albumId, isLiked } = options;
     return this.repository.find({
@@ -41,6 +43,7 @@ export class ActivityRepository implements IActivityRepository {
     await this.repository.delete(id);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
   getStatistics(assetId: string, albumId: string): Promise<number> {
     return this.repository.count({
       where: { assetId, albumId, isLiked: false },
diff --git a/server/src/infra/repositories/album.repository.ts b/server/src/infra/repositories/album.repository.ts
index e6c279726..8a63897ed 100644
--- a/server/src/infra/repositories/album.repository.ts
+++ b/server/src/infra/repositories/album.repository.ts
@@ -4,6 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
 import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
 import { dataSource } from '../database.config';
 import { AlbumEntity, AssetEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class AlbumRepository implements IAlbumRepository {
@@ -13,6 +14,7 @@ export class AlbumRepository implements IAlbumRepository {
     @InjectDataSource() private dataSource: DataSource,
   ) {}
 
+  @GenerateSql({ params: [DummyValue.UUID, {}] })
   getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
     const relations: FindOptionsRelations<AlbumEntity> = {
       owner: true,
@@ -36,6 +38,7 @@ export class AlbumRepository implements IAlbumRepository {
     return this.repository.findOne({ where: { id }, relations, order });
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID]] })
   getByIds(ids: string[]): Promise<AlbumEntity[]> {
     return this.repository.find({
       where: {
@@ -48,6 +51,7 @@ export class AlbumRepository implements IAlbumRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
   getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]> {
     return this.repository.find({
       where: [
@@ -59,6 +63,7 @@ export class AlbumRepository implements IAlbumRepository {
     });
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID]] })
   async getMetadataForIds(ids: string[]): Promise<AlbumAssetCount[]> {
     // Guard against running invalid query when ids list is empty.
     if (!ids.length) {
@@ -91,6 +96,7 @@ export class AlbumRepository implements IAlbumRepository {
    *  - Thumbnail references an asset outside the album
    *  - Empty album still has a thumbnail set
    */
+  @GenerateSql()
   async getInvalidThumbnail(): Promise<string[]> {
     // Using dataSource, because there is no direct access to albums_assets_assets.
     const albumHasAssets = this.dataSource
@@ -113,6 +119,7 @@ export class AlbumRepository implements IAlbumRepository {
     return albums.map((album) => album.id);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getOwned(ownerId: string): Promise<AlbumEntity[]> {
     return this.repository.find({
       relations: { sharedUsers: true, sharedLinks: true, owner: true },
@@ -124,6 +131,7 @@ export class AlbumRepository implements IAlbumRepository {
   /**
    * Get albums shared with and shared by owner.
    */
+  @GenerateSql({ params: [DummyValue.UUID] })
   getShared(ownerId: string): Promise<AlbumEntity[]> {
     return this.repository.find({
       relations: { sharedUsers: true, sharedLinks: true, owner: true },
@@ -139,6 +147,7 @@ export class AlbumRepository implements IAlbumRepository {
   /**
    * Get albums of owner that are _not_ shared
    */
+  @GenerateSql({ params: [DummyValue.UUID] })
   getNotShared(ownerId: string): Promise<AlbumEntity[]> {
     return this.repository.find({
       relations: { sharedUsers: true, sharedLinks: true, owner: true },
@@ -159,6 +168,7 @@ export class AlbumRepository implements IAlbumRepository {
     await this.repository.delete({ ownerId: userId });
   }
 
+  @GenerateSql()
   getAll(): Promise<AlbumEntity[]> {
     return this.repository.find({
       relations: {
@@ -167,6 +177,7 @@ export class AlbumRepository implements IAlbumRepository {
     });
   }
 
+  // @GenerateSql({ params: [DummyValue.UUID] })
   async removeAsset(assetId: string): Promise<void> {
     // Using dataSource, because there is no direct access to albums_assets_assets.
     await this.dataSource
@@ -176,6 +187,7 @@ export class AlbumRepository implements IAlbumRepository {
       .where('"albums_assets_assets"."assetsId" = :assetId', { assetId });
   }
 
+  @GenerateSql({ params: [{ albumId: DummyValue.UUID, assetIds: [DummyValue.UUID] }] })
   async removeAssets(asset: AlbumAssets): Promise<void> {
     await this.dataSource
       .createQueryBuilder()
@@ -195,6 +207,7 @@ export class AlbumRepository implements IAlbumRepository {
    * @param assetIds Optional list of asset IDs to filter on.
    * @returns Set of Asset IDs for the given album ID.
    */
+  @GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] }, { name: 'no assets', params: [DummyValue.UUID] })
   async getAssetIds(albumId: string, assetIds?: string[]): Promise<Set<string>> {
     const query = this.dataSource
       .createQueryBuilder()
@@ -210,6 +223,7 @@ export class AlbumRepository implements IAlbumRepository {
     return new Set(result.map((row) => row['assetId']));
   }
 
+  @GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] })
   hasAsset(asset: AlbumAsset): Promise<boolean> {
     return this.repository.exist({
       where: {
@@ -224,6 +238,7 @@ export class AlbumRepository implements IAlbumRepository {
     });
   }
 
+  @GenerateSql({ params: [{ albumId: DummyValue.UUID, assetIds: [DummyValue.UUID] }] })
   async addAssets({ albumId, assetIds }: AlbumAssets): Promise<void> {
     await this.dataSource
       .createQueryBuilder()
@@ -266,6 +281,7 @@ export class AlbumRepository implements IAlbumRepository {
    *
    * @returns Amount of updated album thumbnails or undefined when unknown
    */
+  @GenerateSql()
   async updateThumbnails(): Promise<number | undefined> {
     // Subquery for getting a new thumbnail.
     const newThumbnail = this.assetRepository
diff --git a/server/src/infra/repositories/api-key.repository.ts b/server/src/infra/repositories/api-key.repository.ts
index 2484b0d56..71226a537 100644
--- a/server/src/infra/repositories/api-key.repository.ts
+++ b/server/src/infra/repositories/api-key.repository.ts
@@ -3,9 +3,10 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
 import { APIKeyEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
-export class APIKeyRepository implements IKeyRepository {
+export class ApiKeyRepository implements IKeyRepository {
   constructor(@InjectRepository(APIKeyEntity) private repository: Repository<APIKeyEntity>) {}
 
   async create(dto: Partial<APIKeyEntity>): Promise<APIKeyEntity> {
@@ -21,6 +22,7 @@ export class APIKeyRepository implements IKeyRepository {
     await this.repository.delete({ userId, id });
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   getKey(hashedToken: string): Promise<APIKeyEntity | null> {
     return this.repository.findOne({
       select: {
@@ -35,10 +37,12 @@ export class APIKeyRepository implements IKeyRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
   getById(userId: string, id: string): Promise<APIKeyEntity | null> {
     return this.repository.findOne({ where: { userId, id } });
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   getByUserId(userId: string): Promise<APIKeyEntity[]> {
     return this.repository.find({ where: { userId }, order: { createdAt: 'DESC' } });
   }
diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/infra/repositories/asset.repository.ts
index 59c29a9d2..09ecf6692 100644
--- a/server/src/infra/repositories/asset.repository.ts
+++ b/server/src/infra/repositories/asset.repository.ts
@@ -22,6 +22,7 @@ import _ from 'lodash';
 import { DateTime } from 'luxon';
 import { And, FindOptionsRelations, FindOptionsWhere, In, IsNull, LessThan, Not, Repository } from 'typeorm';
 import { AssetEntity, AssetJobStatusEntity, AssetType, ExifEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 import OptionalBetween from '../utils/optional-between.util';
 import { paginate } from '../utils/pagination.util';
 
@@ -185,6 +186,7 @@ export class AssetRepository implements IAssetRepository {
     return this.repository.save(asset);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.DATE] })
   getByDate(ownerId: string, date: Date): Promise<AssetEntity[]> {
     // For reference of a correct approach although slower
 
@@ -219,6 +221,7 @@ export class AssetRepository implements IAssetRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
   getByDayOfYear(ownerId: string, { day, month }: MonthDay): Promise<AssetEntity[]> {
     return this.repository
       .createQueryBuilder('entity')
@@ -240,6 +243,7 @@ export class AssetRepository implements IAssetRepository {
       .getMany();
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID]] })
   getByIds(ids: string[], relations?: FindOptionsRelations<AssetEntity>): Promise<AssetEntity[]> {
     if (!relations) {
       relations = {
@@ -259,6 +263,7 @@ export class AssetRepository implements IAssetRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async deleteAll(ownerId: string): Promise<void> {
     await this.repository.delete({ ownerId });
   }
@@ -291,12 +296,14 @@ export class AssetRepository implements IAssetRepository {
     });
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID]] })
   getByLibraryId(libraryIds: string[]): Promise<AssetEntity[]> {
     return this.repository.find({
       where: { library: { id: In(libraryIds) } },
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
   getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string): Promise<AssetEntity | null> {
     return this.repository.findOne({
       where: { library: { id: libraryId }, originalPath: originalPath },
@@ -333,6 +340,7 @@ export class AssetRepository implements IAssetRepository {
    *
    * @returns Promise<string[]> - Array of assetIds belong to the device
    */
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
   async getAllByDeviceId(ownerId: string, deviceId: string): Promise<string[]> {
     const items = await this.repository.find({
       select: { deviceAssetId: true },
@@ -347,6 +355,7 @@ export class AssetRepository implements IAssetRepository {
     return items.map((asset) => asset.deviceAssetId);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getById(id: string): Promise<AssetEntity | null> {
     return this.repository.findOne({
       where: { id },
@@ -362,6 +371,7 @@ export class AssetRepository implements IAssetRepository {
     });
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID], { deviceId: DummyValue.STRING }] })
   async updateAll(ids: string[], options: Partial<AssetEntity>): Promise<void> {
     await this.repository.update({ id: In(ids) }, options);
   }
@@ -395,6 +405,7 @@ export class AssetRepository implements IAssetRepository {
     await this.repository.remove(asset);
   }
 
+  @GenerateSql({ params: [[DummyValue.UUID], DummyValue.BUFFER] })
   getByChecksum(userId: string, checksum: Buffer): Promise<AssetEntity | null> {
     return this.repository.findOne({ where: { ownerId: userId, checksum } });
   }
@@ -417,6 +428,14 @@ export class AssetRepository implements IAssetRepository {
     });
   }
 
+  @GenerateSql(
+    ...Object.values(WithProperty)
+      .filter((property) => property !== WithProperty.IS_OFFLINE)
+      .map((property) => ({
+        name: property,
+        params: [DummyValue.PAGINATION, property],
+      })),
+  )
   getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated<AssetEntity> {
     let relations: FindOptionsRelations<AssetEntity> = {};
     let where: FindOptionsWhere<AssetEntity> | FindOptionsWhere<AssetEntity>[] = {};
diff --git a/server/src/infra/repositories/library.repository.ts b/server/src/infra/repositories/library.repository.ts
index 2b42b3cb5..155c3d9be 100644
--- a/server/src/infra/repositories/library.repository.ts
+++ b/server/src/infra/repositories/library.repository.ts
@@ -4,11 +4,13 @@ import { InjectRepository } from '@nestjs/typeorm';
 import { IsNull, Not } from 'typeorm';
 import { Repository } from 'typeorm/repository/Repository';
 import { LibraryEntity, LibraryType } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class LibraryRepository implements ILibraryRepository {
   constructor(@InjectRepository(LibraryEntity) private repository: Repository<LibraryEntity>) {}
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   get(id: string, withDeleted = false): Promise<LibraryEntity | null> {
     return this.repository.findOneOrFail({
       where: {
@@ -19,6 +21,7 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   existsByName(name: string, withDeleted = false): Promise<boolean> {
     return this.repository.exist({
       where: {
@@ -28,10 +31,12 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getCountForUser(ownerId: string): Promise<number> {
     return this.repository.countBy({ ownerId });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getDefaultUploadLibrary(ownerId: string): Promise<LibraryEntity | null> {
     return this.repository.findOne({
       where: {
@@ -44,6 +49,7 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getUploadLibraryCount(ownerId: string): Promise<number> {
     return this.repository.count({
       where: {
@@ -53,6 +59,7 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getAllByUserId(ownerId: string, type?: LibraryType): Promise<LibraryEntity[]> {
     return this.repository.find({
       where: {
@@ -69,6 +76,7 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql({ params: [] })
   getAll(withDeleted = false, type?: LibraryType): Promise<LibraryEntity[]> {
     return this.repository.find({
       where: { type },
@@ -82,6 +90,7 @@ export class LibraryRepository implements ILibraryRepository {
     });
   }
 
+  @GenerateSql()
   getAllDeleted(): Promise<LibraryEntity[]> {
     return this.repository.find({
       where: {
@@ -114,6 +123,7 @@ export class LibraryRepository implements ILibraryRepository {
     return this.save(library);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async getStatistics(id: string): Promise<LibraryStatsResponseDto> {
     const stats = await this.repository
       .createQueryBuilder('libraries')
@@ -134,6 +144,7 @@ export class LibraryRepository implements ILibraryRepository {
     };
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async getOnlineAssetPaths(libraryId: string): Promise<string[]> {
     // Return all non-offline asset paths for a given library
     const rawResults = await this.repository
@@ -153,6 +164,7 @@ export class LibraryRepository implements ILibraryRepository {
     return results;
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async getAssetIds(libraryId: string, withDeleted = false): Promise<string[]> {
     let query = await this.repository
       .createQueryBuilder('library')
diff --git a/server/src/infra/repositories/move.repository.ts b/server/src/infra/repositories/move.repository.ts
index f909b0f20..f7995b54e 100644
--- a/server/src/infra/repositories/move.repository.ts
+++ b/server/src/infra/repositories/move.repository.ts
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
 import { MoveEntity, PathType } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class MoveRepository implements IMoveRepository {
@@ -12,6 +13,7 @@ export class MoveRepository implements IMoveRepository {
     return this.repository.save(entity);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
   getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | null> {
     return this.repository.findOne({ where: { entityId, pathType } });
   }
diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/infra/repositories/person.repository.ts
index a986a0e0c..e3c0ac26a 100644
--- a/server/src/infra/repositories/person.repository.ts
+++ b/server/src/infra/repositories/person.repository.ts
@@ -9,6 +9,7 @@ import {
 import { InjectRepository } from '@nestjs/typeorm';
 import { In, Repository } from 'typeorm';
 import { AssetEntity, AssetFaceEntity, PersonEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 export class PersonRepository implements IPersonRepository {
   constructor(
@@ -36,6 +37,7 @@ export class PersonRepository implements IPersonRepository {
     return assetIds;
   }
 
+  @GenerateSql({ params: [{ oldPersonId: DummyValue.UUID, newPersonId: DummyValue.UUID }] })
   async reassignFaces({ oldPersonId, newPersonId }: UpdateFacesData): Promise<number> {
     const result = await this.assetFaceRepository
       .createQueryBuilder()
@@ -57,18 +59,22 @@ export class PersonRepository implements IPersonRepository {
     return people.length;
   }
 
+  @GenerateSql()
   getAllFaces(): Promise<AssetFaceEntity[]> {
     return this.assetFaceRepository.find({ relations: { asset: true }, withDeleted: true });
   }
 
+  @GenerateSql()
   getAll(): Promise<PersonEntity[]> {
     return this.personRepository.find();
   }
 
+  @GenerateSql()
   getAllWithoutThumbnail(): Promise<PersonEntity[]> {
     return this.personRepository.findBy({ thumbnailPath: '' });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getAllForUser(userId: string, options?: PersonSearchOptions): Promise<PersonEntity[]> {
     const queryBuilder = this.personRepository
       .createQueryBuilder('person')
@@ -89,6 +95,7 @@ export class PersonRepository implements IPersonRepository {
     return queryBuilder.getMany();
   }
 
+  @GenerateSql()
   getAllWithoutFaces(): Promise<PersonEntity[]> {
     return this.personRepository
       .createQueryBuilder('person')
@@ -99,10 +106,12 @@ export class PersonRepository implements IPersonRepository {
       .getMany();
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getById(personId: string): Promise<PersonEntity | null> {
     return this.personRepository.findOne({ where: { id: personId } });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING, { withHidden: true }] })
   getByName(userId: string, personName: string, { withHidden }: PersonNameSearchOptions): Promise<PersonEntity[]> {
     const queryBuilder = this.personRepository
       .createQueryBuilder('person')
@@ -121,6 +130,7 @@ export class PersonRepository implements IPersonRepository {
     return queryBuilder.getMany();
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async getStatistics(personId: string): Promise<PersonStatistics> {
     return {
       assets: await this.assetFaceRepository
@@ -135,6 +145,7 @@ export class PersonRepository implements IPersonRepository {
     };
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getAssets(personId: string): Promise<AssetEntity[]> {
     return this.assetRepository.find({
       where: {
@@ -171,10 +182,12 @@ export class PersonRepository implements IPersonRepository {
     return this.personRepository.findOneByOrFail({ id });
   }
 
+  @GenerateSql({ params: [[{ assetId: DummyValue.UUID, personId: DummyValue.UUID }]] })
   async getFacesByIds(ids: AssetFaceId[]): Promise<AssetFaceEntity[]> {
     return this.assetFaceRepository.find({ where: ids, relations: { asset: true }, withDeleted: true });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async getRandomFace(personId: string): Promise<AssetFaceEntity | null> {
     return this.assetFaceRepository.findOneBy({ personId });
   }
diff --git a/server/src/infra/repositories/shared-link.repository.ts b/server/src/infra/repositories/shared-link.repository.ts
index 127efee43..ae8826f79 100644
--- a/server/src/infra/repositories/shared-link.repository.ts
+++ b/server/src/infra/repositories/shared-link.repository.ts
@@ -3,11 +3,13 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
 import { SharedLinkEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class SharedLinkRepository implements ISharedLinkRepository {
   constructor(@InjectRepository(SharedLinkEntity) private repository: Repository<SharedLinkEntity>) {}
 
+  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
   get(userId: string, id: string): Promise<SharedLinkEntity | null> {
     return this.repository.findOne({
       where: {
@@ -39,6 +41,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   getAll(userId: string): Promise<SharedLinkEntity[]> {
     return this.repository.find({
       where: {
@@ -56,6 +59,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
     });
   }
 
+  @GenerateSql({ params: [DummyValue.BUFFER] })
   async getByKey(key: Buffer): Promise<SharedLinkEntity | null> {
     return await this.repository.findOne({
       where: {
diff --git a/server/src/infra/repositories/system-config.repository.ts b/server/src/infra/repositories/system-config.repository.ts
index 0a66c2f22..57eb6c1fd 100644
--- a/server/src/infra/repositories/system-config.repository.ts
+++ b/server/src/infra/repositories/system-config.repository.ts
@@ -4,6 +4,7 @@ import axios from 'axios';
 import { readFile } from 'fs/promises';
 import { In, Repository } from 'typeorm';
 import { SystemConfigEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 export class SystemConfigRepository implements ISystemConfigRepository {
   constructor(
@@ -14,6 +15,7 @@ export class SystemConfigRepository implements ISystemConfigRepository {
     return axios.get(url).then((response) => response.data);
   }
 
+  @GenerateSql()
   load(): Promise<SystemConfigEntity[]> {
     return this.repository.find();
   }
@@ -26,6 +28,7 @@ export class SystemConfigRepository implements ISystemConfigRepository {
     return this.repository.save(items);
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   async deleteKeys(keys: string[]): Promise<void> {
     await this.repository.delete({ key: In(keys) });
   }
diff --git a/server/src/infra/repositories/user-token.repository.ts b/server/src/infra/repositories/user-token.repository.ts
index cb83134a3..b5656d922 100644
--- a/server/src/infra/repositories/user-token.repository.ts
+++ b/server/src/infra/repositories/user-token.repository.ts
@@ -3,11 +3,13 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
 import { UserTokenEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class UserTokenRepository implements IUserTokenRepository {
   constructor(@InjectRepository(UserTokenEntity) private repository: Repository<UserTokenEntity>) {}
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   getByToken(token: string): Promise<UserTokenEntity | null> {
     return this.repository.findOne({ where: { token }, relations: { user: true } });
   }
@@ -35,6 +37,7 @@ export class UserTokenRepository implements IUserTokenRepository {
     return this.repository.save(userToken);
   }
 
+  @GenerateSql({ params: [DummyValue.UUID] })
   async delete(id: string): Promise<void> {
     await this.repository.delete({ id });
   }
diff --git a/server/src/infra/repositories/user.repository.ts b/server/src/infra/repositories/user.repository.ts
index b84adb2fd..d1b1c0d5e 100644
--- a/server/src/infra/repositories/user.repository.ts
+++ b/server/src/infra/repositories/user.repository.ts
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { IsNull, Not, Repository } from 'typeorm';
 import { UserEntity } from '../entities';
+import { DummyValue, GenerateSql } from '../infra.util';
 
 @Injectable()
 export class UserRepository implements IUserRepository {
@@ -16,14 +17,17 @@ export class UserRepository implements IUserRepository {
     });
   }
 
+  @GenerateSql()
   async getAdmin(): Promise<UserEntity | null> {
     return this.userRepository.findOne({ where: { isAdmin: true } });
   }
 
+  @GenerateSql()
   async hasAdmin(): Promise<boolean> {
     return this.userRepository.exist({ where: { isAdmin: true } });
   }
 
+  @GenerateSql({ params: [DummyValue.EMAIL] })
   async getByEmail(email: string, withPassword?: boolean): Promise<UserEntity | null> {
     let builder = this.userRepository.createQueryBuilder('user').where({ email });
 
@@ -34,10 +38,12 @@ export class UserRepository implements IUserRepository {
     return builder.getOne();
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   async getByStorageLabel(storageLabel: string): Promise<UserEntity | null> {
     return this.userRepository.findOne({ where: { storageLabel } });
   }
 
+  @GenerateSql({ params: [DummyValue.STRING] })
   async getByOAuthId(oauthId: string): Promise<UserEntity | null> {
     return this.userRepository.findOne({ where: { oauthId } });
   }
@@ -76,6 +82,7 @@ export class UserRepository implements IUserRepository {
     return this.userRepository.recover(user);
   }
 
+  @GenerateSql()
   async getUserStats(): Promise<UserStatsQueryResponse[]> {
     const stats = await this.userRepository
       .createQueryBuilder('users')
diff --git a/server/src/infra/sql-generator/index.ts b/server/src/infra/sql-generator/index.ts
new file mode 100644
index 000000000..78b412249
--- /dev/null
+++ b/server/src/infra/sql-generator/index.ts
@@ -0,0 +1,168 @@
+import { INestApplication } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { Test } from '@nestjs/testing';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { mkdir, rm, writeFile } from 'fs/promises';
+import { join } from 'path';
+import { databaseConfig } from '../database.config';
+import { databaseEntities } from '../entities';
+import { GENERATE_SQL_KEY, GenerateSqlQueries } from '../infra.util';
+import {
+  AccessRepository,
+  AlbumRepository,
+  ApiKeyRepository,
+  AssetRepository,
+  AuditRepository,
+  LibraryRepository,
+  MoveRepository,
+  PartnerRepository,
+  PersonRepository,
+  SharedLinkRepository,
+  SystemConfigRepository,
+  SystemMetadataRepository,
+  TagRepository,
+  UserRepository,
+  UserTokenRepository,
+} from '../repositories';
+import { SqlLogger } from './sql.logger';
+
+const reflector = new Reflector();
+const repositories = [
+  AccessRepository,
+  AlbumRepository,
+  ApiKeyRepository,
+  AssetRepository,
+  AuditRepository,
+  LibraryRepository,
+  MoveRepository,
+  PartnerRepository,
+  PersonRepository,
+  SharedLinkRepository,
+  SystemConfigRepository,
+  SystemMetadataRepository,
+  TagRepository,
+  UserTokenRepository,
+  UserRepository,
+];
+
+type Repository = (typeof repositories)[0];
+type SqlGeneratorOptions = { targetDir: string };
+
+class SqlGenerator {
+  private app: INestApplication | null = null;
+  private sqlLogger = new SqlLogger();
+  private results: Record<string, string[]> = {};
+
+  constructor(private options: SqlGeneratorOptions) {}
+
+  async run() {
+    try {
+      await this.setup();
+      for (const Repository of repositories) {
+        await this.process(Repository);
+      }
+      await this.write();
+      this.stats();
+    } finally {
+      await this.close();
+    }
+  }
+
+  private async setup() {
+    await rm(this.options.targetDir, { force: true, recursive: true });
+    await mkdir(this.options.targetDir);
+
+    const moduleFixture = await Test.createTestingModule({
+      imports: [
+        TypeOrmModule.forRoot({
+          ...databaseConfig,
+          entities: databaseEntities,
+          logging: ['query'],
+          logger: this.sqlLogger,
+        }),
+        TypeOrmModule.forFeature(databaseEntities),
+      ],
+      providers: repositories,
+    }).compile();
+
+    this.app = await moduleFixture.createNestApplication().init();
+  }
+
+  async process(Repository: Repository) {
+    if (!this.app) {
+      throw new Error('Not initialized');
+    }
+
+    const data: string[] = [`-- NOTE: This file is auto generated by ./sql-generator`];
+    const instance = this.app.get<Repository>(Repository);
+    const properties = Object.getOwnPropertyNames(Repository.prototype) as Array<keyof typeof Repository>;
+    for (const key of properties) {
+      const target = instance[key];
+      if (!(target instanceof Function)) {
+        continue;
+      }
+
+      const queries = reflector.get<GenerateSqlQueries[] | undefined>(GENERATE_SQL_KEY, target);
+      if (!queries) {
+        continue;
+      }
+
+      // empty decorator implies calling with no arguments
+      if (queries.length === 0) {
+        queries.push({ params: [] });
+      }
+
+      for (const { name, params } of queries) {
+        let queryLabel = `${Repository.name}.${key}`;
+        if (name) {
+          queryLabel += ` (${name})`;
+        }
+
+        this.sqlLogger.clear();
+
+        // errors still generate sql, which is all we care about
+        await target.apply(instance, params).catch(() => null);
+
+        if (this.sqlLogger.queries.length === 0) {
+          console.warn(`No queries recorded for ${queryLabel}`);
+          continue;
+        }
+
+        data.push([`-- ${queryLabel}`, ...this.sqlLogger.queries].join('\n'));
+      }
+    }
+
+    this.results[Repository.name] = data;
+  }
+
+  private async write() {
+    for (const [repoName, data] of Object.entries(this.results)) {
+      const filename = repoName.replace(/[A-Z]/g, (letter) => `.${letter.toLowerCase()}`).replace('.', '');
+      const file = join(this.options.targetDir, `${filename}.sql`);
+      await writeFile(file, data.join('\n\n') + '\n');
+    }
+  }
+
+  private stats() {
+    console.log(`Wrote ${Object.keys(this.results).length} files`);
+    console.log(`Generated ${Object.values(this.results).flat().length} queries`);
+  }
+
+  private async close() {
+    if (this.app) {
+      await this.app.close();
+    }
+  }
+}
+
+new SqlGenerator({ targetDir: './src/infra/sql' })
+  .run()
+  .then(() => {
+    console.log('Done');
+    process.exit(0);
+  })
+  .catch((error) => {
+    console.error(error);
+    console.log('Something went wrong');
+    process.exit(1);
+  });
diff --git a/server/src/infra/sql-generator/sql.logger.ts b/server/src/infra/sql-generator/sql.logger.ts
new file mode 100644
index 000000000..78c3df148
--- /dev/null
+++ b/server/src/infra/sql-generator/sql.logger.ts
@@ -0,0 +1,27 @@
+import { Logger } from 'typeorm';
+
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const { format } = require('sql-formatter');
+
+export class SqlLogger implements Logger {
+  queries: string[] = [];
+  errors: Array<{ error: string | Error; query: string }> = [];
+
+  clear() {
+    this.queries = [];
+    this.errors = [];
+  }
+
+  logQuery(query: string) {
+    this.queries.push(format(query, { language: 'postgresql' }));
+  }
+
+  logQueryError(error: string | Error, query: string) {
+    this.errors.push({ error, query });
+  }
+
+  logQuerySlow() {}
+  logSchemaBuild() {}
+  logMigration() {}
+  log() {}
+}
diff --git a/server/src/infra/sql/access.repository.sql b/server/src/infra/sql/access.repository.sql
new file mode 100644
index 000000000..21f9f116b
--- /dev/null
+++ b/server/src/infra/sql/access.repository.sql
@@ -0,0 +1 @@
+-- NOTE: This file is auto generated by ./sql-generator
diff --git a/server/src/infra/sql/album.repository.sql b/server/src/infra/sql/album.repository.sql
new file mode 100644
index 000000000..777edb097
--- /dev/null
+++ b/server/src/infra/sql/album.repository.sql
@@ -0,0 +1,613 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- AlbumRepository.getById
+SELECT DISTINCT
+  "distinctAlias"."AlbumEntity_id" AS "ids_AlbumEntity_id"
+FROM
+  (
+    SELECT
+      "AlbumEntity"."id" AS "AlbumEntity_id",
+      "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+      "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+      "AlbumEntity"."description" AS "AlbumEntity_description",
+      "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+      "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+      "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+      "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+      "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+      "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+      "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+      "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+      "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+      "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+      "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+      "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+      "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+      "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+      "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+      "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+      "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+      "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+      "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled",
+      "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+      "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+      "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+      "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+      "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+      "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+      "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+      "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+      "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+      "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+      "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+      "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+      "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+      "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled",
+      "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
+      "AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
+      "AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
+      "AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
+      "AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
+      "AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
+      "AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
+      "AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
+      "AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
+      "AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
+      "AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
+      "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId"
+    FROM
+      "albums" "AlbumEntity"
+      LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+      AND (
+        "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+      )
+      LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+      LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+      AND (
+        "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+      )
+      LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
+    WHERE
+      (("AlbumEntity"."id" = $1))
+      AND ("AlbumEntity"."deletedAt" IS NULL)
+  ) "distinctAlias"
+ORDER BY
+  "AlbumEntity_id" ASC
+LIMIT
+  1
+
+-- AlbumRepository.getByIds
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled",
+  "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+  "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+  "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+  "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+  "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+  "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+  "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+  "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+  LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+  AND (
+    "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+  )
+WHERE
+  (("AlbumEntity"."id" IN ($1)))
+  AND ("AlbumEntity"."deletedAt" IS NULL)
+
+-- AlbumRepository.getByAssetId
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled",
+  "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+  "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+  "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+  "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+  "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+  "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+  "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+  "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+  LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+  AND (
+    "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+  )
+  LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets" ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets" ON "AlbumEntity__AlbumEntity_assets"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
+  AND (
+    "AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
+  )
+WHERE
+  (
+    (
+      (
+        "AlbumEntity"."ownerId" = $1
+        AND "AlbumEntity__AlbumEntity_assets"."id" = $2
+      )
+      OR (
+        "AlbumEntity__AlbumEntity_sharedUsers"."id" = $3
+        AND "AlbumEntity__AlbumEntity_assets"."id" = $4
+      )
+    )
+  )
+  AND ("AlbumEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AlbumEntity"."createdAt" DESC
+
+-- AlbumRepository.getMetadataForIds
+SELECT
+  "album"."id" AS "album_id",
+  MIN("assets"."fileCreatedAt") AS "start_date",
+  MAX("assets"."fileCreatedAt") AS "end_date",
+  COUNT("album_assets"."assetsId") AS "asset_count"
+FROM
+  "albums" "album"
+  LEFT JOIN "albums_assets_assets" "album_assets" ON "album_assets"."albumsId" = "album"."id"
+  LEFT JOIN "assets" "assets" ON "assets"."id" = "album_assets"."assetsId"
+  AND "assets"."deletedAt" IS NULL
+WHERE
+  ("album"."id" IN ($1))
+  AND ("album"."deletedAt" IS NULL)
+GROUP BY
+  "album"."id"
+
+-- AlbumRepository.getInvalidThumbnail
+SELECT
+  "albums"."id" AS "albums_id"
+FROM
+  "albums" "albums"
+WHERE
+  (
+    "albums"."albumThumbnailAssetId" IS NULL
+    AND EXISTS (
+      SELECT
+        1
+      FROM
+        "albums_assets_assets" "albums_assets"
+      WHERE
+        "albums"."id" = "albums_assets"."albumsId"
+    )
+    OR "albums"."albumThumbnailAssetId" IS NOT NULL
+    AND NOT EXISTS (
+      SELECT
+        1
+      FROM
+        "albums_assets_assets" "albums_assets"
+      WHERE
+        "albums"."id" = "albums_assets"."albumsId"
+        AND "albums"."albumThumbnailAssetId" = "albums_assets"."assetsId"
+    )
+  )
+  AND ("albums"."deletedAt" IS NULL)
+
+-- AlbumRepository.getOwned
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+  "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+  "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+  "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+  "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+  "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+  "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+  "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled",
+  "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
+  "AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
+  "AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
+  "AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
+  "AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
+  "AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
+  "AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
+  "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+  AND (
+    "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+  )
+  LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  (("AlbumEntity"."ownerId" = $1))
+  AND ("AlbumEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AlbumEntity"."createdAt" DESC
+
+-- AlbumRepository.getShared
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+  "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+  "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+  "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+  "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+  "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+  "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+  "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled",
+  "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
+  "AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
+  "AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
+  "AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
+  "AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
+  "AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
+  "AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
+  "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+  AND (
+    "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+  )
+  LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  (
+    (
+      ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $1)
+      OR (
+        "AlbumEntity__AlbumEntity_sharedLinks"."userId" = $2
+      )
+      OR (
+        "AlbumEntity"."ownerId" = $3
+        AND NOT (
+          "AlbumEntity__AlbumEntity_sharedUsers"."id" IS NULL
+        )
+      )
+    )
+  )
+  AND ("AlbumEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AlbumEntity"."createdAt" DESC
+
+-- AlbumRepository.getNotShared
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_sharedUsers"."id" AS "AlbumEntity__AlbumEntity_sharedUsers_id",
+  "AlbumEntity__AlbumEntity_sharedUsers"."name" AS "AlbumEntity__AlbumEntity_sharedUsers_name",
+  "AlbumEntity__AlbumEntity_sharedUsers"."avatarColor" AS "AlbumEntity__AlbumEntity_sharedUsers_avatarColor",
+  "AlbumEntity__AlbumEntity_sharedUsers"."isAdmin" AS "AlbumEntity__AlbumEntity_sharedUsers_isAdmin",
+  "AlbumEntity__AlbumEntity_sharedUsers"."email" AS "AlbumEntity__AlbumEntity_sharedUsers_email",
+  "AlbumEntity__AlbumEntity_sharedUsers"."storageLabel" AS "AlbumEntity__AlbumEntity_sharedUsers_storageLabel",
+  "AlbumEntity__AlbumEntity_sharedUsers"."externalPath" AS "AlbumEntity__AlbumEntity_sharedUsers_externalPath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."oauthId" AS "AlbumEntity__AlbumEntity_sharedUsers_oauthId",
+  "AlbumEntity__AlbumEntity_sharedUsers"."profileImagePath" AS "AlbumEntity__AlbumEntity_sharedUsers_profileImagePath",
+  "AlbumEntity__AlbumEntity_sharedUsers"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_sharedUsers_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_sharedUsers"."createdAt" AS "AlbumEntity__AlbumEntity_sharedUsers_createdAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_deletedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."updatedAt" AS "AlbumEntity__AlbumEntity_sharedUsers_updatedAt",
+  "AlbumEntity__AlbumEntity_sharedUsers"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_sharedUsers_memoriesEnabled",
+  "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
+  "AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
+  "AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
+  "AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
+  "AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
+  "AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
+  "AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
+  "AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
+  "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers" ON "AlbumEntity__AlbumEntity_sharedUsers"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
+  AND (
+    "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
+  )
+  LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  (
+    (
+      "AlbumEntity"."ownerId" = $1
+      AND "AlbumEntity__AlbumEntity_sharedUsers"."id" IS NULL
+      AND "AlbumEntity__AlbumEntity_sharedLinks"."id" IS NULL
+    )
+  )
+  AND ("AlbumEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AlbumEntity"."createdAt" DESC
+
+-- AlbumRepository.getAll
+SELECT
+  "AlbumEntity"."id" AS "AlbumEntity_id",
+  "AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
+  "AlbumEntity"."albumName" AS "AlbumEntity_albumName",
+  "AlbumEntity"."description" AS "AlbumEntity_description",
+  "AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
+  "AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
+  "AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
+  "AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
+  "AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
+  "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
+  "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
+  "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor",
+  "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
+  "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
+  "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
+  "AlbumEntity__AlbumEntity_owner"."externalPath" AS "AlbumEntity__AlbumEntity_owner_externalPath",
+  "AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
+  "AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
+  "AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
+  "AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
+  "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
+  "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
+  "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled"
+FROM
+  "albums" "AlbumEntity"
+  LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
+  AND (
+    "AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  "AlbumEntity"."deletedAt" IS NULL
+
+-- AlbumRepository.removeAssets
+DELETE FROM "albums_assets_assets"
+WHERE
+  (
+    "albumsId" = $1
+    AND "assetsId" IN ($2)
+  )
+
+-- AlbumRepository.getAssetIds
+SELECT
+  "albums_assets"."assetsId" AS "assetId"
+FROM
+  "albums_assets_assets" "albums_assets"
+WHERE
+  "albums_assets"."albumsId" = $1
+  AND "albums_assets"."assetsId" IN ($2)
+
+-- AlbumRepository.getAssetIds (no assets)
+SELECT
+  "albums_assets"."assetsId" AS "assetId"
+FROM
+  "albums_assets_assets" "albums_assets"
+WHERE
+  "albums_assets"."albumsId" = $1
+
+-- AlbumRepository.hasAsset
+SELECT
+  1 AS "row_exists"
+FROM
+  (
+    SELECT
+      1 AS dummy_column
+  ) "dummy_table"
+WHERE
+  EXISTS (
+    SELECT
+      1
+    FROM
+      "albums" "AlbumEntity"
+      LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets" ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId" = "AlbumEntity"."id"
+      LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets" ON "AlbumEntity__AlbumEntity_assets"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
+      AND (
+        "AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
+      )
+    WHERE
+      (
+        (
+          "AlbumEntity"."id" = $1
+          AND "AlbumEntity__AlbumEntity_assets"."id" = $2
+        )
+      )
+      AND ("AlbumEntity"."deletedAt" IS NULL)
+  )
+LIMIT
+  1
+
+-- AlbumRepository.addAssets
+INSERT INTO
+  "albums_assets_assets" ("albumsId", "assetsId")
+VALUES
+  ($1, $2)
+
+-- AlbumRepository.updateThumbnails
+UPDATE "albums"
+SET
+  "albumThumbnailAssetId" = (
+    SELECT
+      "albums_assets2"."assetsId"
+    FROM
+      "assets" "assets",
+      "albums_assets_assets" "albums_assets2"
+    WHERE
+      (
+        "albums_assets2"."assetsId" = "assets"."id"
+        AND "albums_assets2"."albumsId" = "albums"."id"
+      )
+      AND ("assets"."deletedAt" IS NULL)
+    ORDER BY
+      "assets"."fileCreatedAt" DESC
+    LIMIT
+      1
+  ),
+  "updatedAt" = CURRENT_TIMESTAMP
+WHERE
+  "albums"."albumThumbnailAssetId" IS NULL
+  AND EXISTS (
+    SELECT
+      1
+    FROM
+      "albums_assets_assets" "albums_assets"
+    WHERE
+      "albums"."id" = "albums_assets"."albumsId"
+  )
+  OR "albums"."albumThumbnailAssetId" IS NOT NULL
+  AND NOT EXISTS (
+    SELECT
+      1
+    FROM
+      "albums_assets_assets" "albums_assets"
+    WHERE
+      "albums"."id" = "albums_assets"."albumsId"
+      AND "albums"."albumThumbnailAssetId" = "albums_assets"."assetsId"
+  )
diff --git a/server/src/infra/sql/api.key.repository.sql b/server/src/infra/sql/api.key.repository.sql
new file mode 100644
index 000000000..7f26d8575
--- /dev/null
+++ b/server/src/infra/sql/api.key.repository.sql
@@ -0,0 +1,69 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- ApiKeyRepository.getKey
+SELECT DISTINCT
+  "distinctAlias"."APIKeyEntity_id" AS "ids_APIKeyEntity_id"
+FROM
+  (
+    SELECT
+      "APIKeyEntity"."id" AS "APIKeyEntity_id",
+      "APIKeyEntity"."key" AS "APIKeyEntity_key",
+      "APIKeyEntity"."userId" AS "APIKeyEntity_userId",
+      "APIKeyEntity__APIKeyEntity_user"."id" AS "APIKeyEntity__APIKeyEntity_user_id",
+      "APIKeyEntity__APIKeyEntity_user"."name" AS "APIKeyEntity__APIKeyEntity_user_name",
+      "APIKeyEntity__APIKeyEntity_user"."avatarColor" AS "APIKeyEntity__APIKeyEntity_user_avatarColor",
+      "APIKeyEntity__APIKeyEntity_user"."isAdmin" AS "APIKeyEntity__APIKeyEntity_user_isAdmin",
+      "APIKeyEntity__APIKeyEntity_user"."email" AS "APIKeyEntity__APIKeyEntity_user_email",
+      "APIKeyEntity__APIKeyEntity_user"."storageLabel" AS "APIKeyEntity__APIKeyEntity_user_storageLabel",
+      "APIKeyEntity__APIKeyEntity_user"."externalPath" AS "APIKeyEntity__APIKeyEntity_user_externalPath",
+      "APIKeyEntity__APIKeyEntity_user"."oauthId" AS "APIKeyEntity__APIKeyEntity_user_oauthId",
+      "APIKeyEntity__APIKeyEntity_user"."profileImagePath" AS "APIKeyEntity__APIKeyEntity_user_profileImagePath",
+      "APIKeyEntity__APIKeyEntity_user"."shouldChangePassword" AS "APIKeyEntity__APIKeyEntity_user_shouldChangePassword",
+      "APIKeyEntity__APIKeyEntity_user"."createdAt" AS "APIKeyEntity__APIKeyEntity_user_createdAt",
+      "APIKeyEntity__APIKeyEntity_user"."deletedAt" AS "APIKeyEntity__APIKeyEntity_user_deletedAt",
+      "APIKeyEntity__APIKeyEntity_user"."updatedAt" AS "APIKeyEntity__APIKeyEntity_user_updatedAt",
+      "APIKeyEntity__APIKeyEntity_user"."memoriesEnabled" AS "APIKeyEntity__APIKeyEntity_user_memoriesEnabled"
+    FROM
+      "api_keys" "APIKeyEntity"
+      LEFT JOIN "users" "APIKeyEntity__APIKeyEntity_user" ON "APIKeyEntity__APIKeyEntity_user"."id" = "APIKeyEntity"."userId"
+      AND (
+        "APIKeyEntity__APIKeyEntity_user"."deletedAt" IS NULL
+      )
+    WHERE
+      ("APIKeyEntity"."key" = $1)
+  ) "distinctAlias"
+ORDER BY
+  "APIKeyEntity_id" ASC
+LIMIT
+  1
+
+-- ApiKeyRepository.getById
+SELECT
+  "APIKeyEntity"."id" AS "APIKeyEntity_id",
+  "APIKeyEntity"."name" AS "APIKeyEntity_name",
+  "APIKeyEntity"."userId" AS "APIKeyEntity_userId",
+  "APIKeyEntity"."createdAt" AS "APIKeyEntity_createdAt",
+  "APIKeyEntity"."updatedAt" AS "APIKeyEntity_updatedAt"
+FROM
+  "api_keys" "APIKeyEntity"
+WHERE
+  (
+    "APIKeyEntity"."userId" = $1
+    AND "APIKeyEntity"."id" = $2
+  )
+LIMIT
+  1
+
+-- ApiKeyRepository.getByUserId
+SELECT
+  "APIKeyEntity"."id" AS "APIKeyEntity_id",
+  "APIKeyEntity"."name" AS "APIKeyEntity_name",
+  "APIKeyEntity"."userId" AS "APIKeyEntity_userId",
+  "APIKeyEntity"."createdAt" AS "APIKeyEntity_createdAt",
+  "APIKeyEntity"."updatedAt" AS "APIKeyEntity_updatedAt"
+FROM
+  "api_keys" "APIKeyEntity"
+WHERE
+  ("APIKeyEntity"."userId" = $1)
+ORDER BY
+  "APIKeyEntity"."createdAt" DESC
diff --git a/server/src/infra/sql/asset.repository.sql b/server/src/infra/sql/asset.repository.sql
new file mode 100644
index 000000000..c970c997b
--- /dev/null
+++ b/server/src/infra/sql/asset.repository.sql
@@ -0,0 +1,614 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- AssetRepository.getByDate
+SELECT
+  "AssetEntity"."id" AS "AssetEntity_id",
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+  "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+  "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+  "AssetEntity"."type" AS "AssetEntity_type",
+  "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+  "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+  "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+  "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+  "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+  "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+  "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+  "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+  "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+  "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+  "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+  "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+  "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+  "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+  "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+  "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+  "AssetEntity"."checksum" AS "AssetEntity_checksum",
+  "AssetEntity"."duration" AS "AssetEntity_duration",
+  "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+  "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+  "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+  "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+  "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId",
+  "AssetEntity__AssetEntity_exifInfo"."assetId" AS "AssetEntity__AssetEntity_exifInfo_assetId",
+  "AssetEntity__AssetEntity_exifInfo"."description" AS "AssetEntity__AssetEntity_exifInfo_description",
+  "AssetEntity__AssetEntity_exifInfo"."exifImageWidth" AS "AssetEntity__AssetEntity_exifInfo_exifImageWidth",
+  "AssetEntity__AssetEntity_exifInfo"."exifImageHeight" AS "AssetEntity__AssetEntity_exifInfo_exifImageHeight",
+  "AssetEntity__AssetEntity_exifInfo"."fileSizeInByte" AS "AssetEntity__AssetEntity_exifInfo_fileSizeInByte",
+  "AssetEntity__AssetEntity_exifInfo"."orientation" AS "AssetEntity__AssetEntity_exifInfo_orientation",
+  "AssetEntity__AssetEntity_exifInfo"."dateTimeOriginal" AS "AssetEntity__AssetEntity_exifInfo_dateTimeOriginal",
+  "AssetEntity__AssetEntity_exifInfo"."modifyDate" AS "AssetEntity__AssetEntity_exifInfo_modifyDate",
+  "AssetEntity__AssetEntity_exifInfo"."timeZone" AS "AssetEntity__AssetEntity_exifInfo_timeZone",
+  "AssetEntity__AssetEntity_exifInfo"."latitude" AS "AssetEntity__AssetEntity_exifInfo_latitude",
+  "AssetEntity__AssetEntity_exifInfo"."longitude" AS "AssetEntity__AssetEntity_exifInfo_longitude",
+  "AssetEntity__AssetEntity_exifInfo"."projectionType" AS "AssetEntity__AssetEntity_exifInfo_projectionType",
+  "AssetEntity__AssetEntity_exifInfo"."city" AS "AssetEntity__AssetEntity_exifInfo_city",
+  "AssetEntity__AssetEntity_exifInfo"."livePhotoCID" AS "AssetEntity__AssetEntity_exifInfo_livePhotoCID",
+  "AssetEntity__AssetEntity_exifInfo"."state" AS "AssetEntity__AssetEntity_exifInfo_state",
+  "AssetEntity__AssetEntity_exifInfo"."country" AS "AssetEntity__AssetEntity_exifInfo_country",
+  "AssetEntity__AssetEntity_exifInfo"."make" AS "AssetEntity__AssetEntity_exifInfo_make",
+  "AssetEntity__AssetEntity_exifInfo"."model" AS "AssetEntity__AssetEntity_exifInfo_model",
+  "AssetEntity__AssetEntity_exifInfo"."lensModel" AS "AssetEntity__AssetEntity_exifInfo_lensModel",
+  "AssetEntity__AssetEntity_exifInfo"."fNumber" AS "AssetEntity__AssetEntity_exifInfo_fNumber",
+  "AssetEntity__AssetEntity_exifInfo"."focalLength" AS "AssetEntity__AssetEntity_exifInfo_focalLength",
+  "AssetEntity__AssetEntity_exifInfo"."iso" AS "AssetEntity__AssetEntity_exifInfo_iso",
+  "AssetEntity__AssetEntity_exifInfo"."exposureTime" AS "AssetEntity__AssetEntity_exifInfo_exposureTime",
+  "AssetEntity__AssetEntity_exifInfo"."profileDescription" AS "AssetEntity__AssetEntity_exifInfo_profileDescription",
+  "AssetEntity__AssetEntity_exifInfo"."colorspace" AS "AssetEntity__AssetEntity_exifInfo_colorspace",
+  "AssetEntity__AssetEntity_exifInfo"."bitsPerSample" AS "AssetEntity__AssetEntity_exifInfo_bitsPerSample",
+  "AssetEntity__AssetEntity_exifInfo"."fps" AS "AssetEntity__AssetEntity_exifInfo_fps",
+  "AssetEntity__AssetEntity_exifInfo"."exifTextSearchableColumn" AS "AssetEntity__AssetEntity_exifInfo_exifTextSearchableColumn"
+FROM
+  "assets" "AssetEntity"
+  LEFT JOIN "exif" "AssetEntity__AssetEntity_exifInfo" ON "AssetEntity__AssetEntity_exifInfo"."assetId" = "AssetEntity"."id"
+WHERE
+  (
+    (
+      "AssetEntity"."ownerId" = $1
+      AND "AssetEntity"."isVisible" = $2
+      AND "AssetEntity"."isArchived" = $3
+      AND NOT ("AssetEntity"."resizePath" IS NULL)
+      AND "AssetEntity"."fileCreatedAt" BETWEEN $4 AND $5
+    )
+  )
+  AND ("AssetEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AssetEntity"."fileCreatedAt" DESC
+
+-- AssetRepository.getByDayOfYear
+SELECT
+  "entity"."id" AS "entity_id",
+  "entity"."deviceAssetId" AS "entity_deviceAssetId",
+  "entity"."ownerId" AS "entity_ownerId",
+  "entity"."libraryId" AS "entity_libraryId",
+  "entity"."deviceId" AS "entity_deviceId",
+  "entity"."type" AS "entity_type",
+  "entity"."originalPath" AS "entity_originalPath",
+  "entity"."resizePath" AS "entity_resizePath",
+  "entity"."webpPath" AS "entity_webpPath",
+  "entity"."thumbhash" AS "entity_thumbhash",
+  "entity"."encodedVideoPath" AS "entity_encodedVideoPath",
+  "entity"."createdAt" AS "entity_createdAt",
+  "entity"."updatedAt" AS "entity_updatedAt",
+  "entity"."deletedAt" AS "entity_deletedAt",
+  "entity"."fileCreatedAt" AS "entity_fileCreatedAt",
+  "entity"."localDateTime" AS "entity_localDateTime",
+  "entity"."fileModifiedAt" AS "entity_fileModifiedAt",
+  "entity"."isFavorite" AS "entity_isFavorite",
+  "entity"."isArchived" AS "entity_isArchived",
+  "entity"."isExternal" AS "entity_isExternal",
+  "entity"."isReadOnly" AS "entity_isReadOnly",
+  "entity"."isOffline" AS "entity_isOffline",
+  "entity"."checksum" AS "entity_checksum",
+  "entity"."duration" AS "entity_duration",
+  "entity"."isVisible" AS "entity_isVisible",
+  "entity"."livePhotoVideoId" AS "entity_livePhotoVideoId",
+  "entity"."originalFileName" AS "entity_originalFileName",
+  "entity"."sidecarPath" AS "entity_sidecarPath",
+  "entity"."stackParentId" AS "entity_stackParentId",
+  "exifInfo"."assetId" AS "exifInfo_assetId",
+  "exifInfo"."description" AS "exifInfo_description",
+  "exifInfo"."exifImageWidth" AS "exifInfo_exifImageWidth",
+  "exifInfo"."exifImageHeight" AS "exifInfo_exifImageHeight",
+  "exifInfo"."fileSizeInByte" AS "exifInfo_fileSizeInByte",
+  "exifInfo"."orientation" AS "exifInfo_orientation",
+  "exifInfo"."dateTimeOriginal" AS "exifInfo_dateTimeOriginal",
+  "exifInfo"."modifyDate" AS "exifInfo_modifyDate",
+  "exifInfo"."timeZone" AS "exifInfo_timeZone",
+  "exifInfo"."latitude" AS "exifInfo_latitude",
+  "exifInfo"."longitude" AS "exifInfo_longitude",
+  "exifInfo"."projectionType" AS "exifInfo_projectionType",
+  "exifInfo"."city" AS "exifInfo_city",
+  "exifInfo"."livePhotoCID" AS "exifInfo_livePhotoCID",
+  "exifInfo"."state" AS "exifInfo_state",
+  "exifInfo"."country" AS "exifInfo_country",
+  "exifInfo"."make" AS "exifInfo_make",
+  "exifInfo"."model" AS "exifInfo_model",
+  "exifInfo"."lensModel" AS "exifInfo_lensModel",
+  "exifInfo"."fNumber" AS "exifInfo_fNumber",
+  "exifInfo"."focalLength" AS "exifInfo_focalLength",
+  "exifInfo"."iso" AS "exifInfo_iso",
+  "exifInfo"."exposureTime" AS "exifInfo_exposureTime",
+  "exifInfo"."profileDescription" AS "exifInfo_profileDescription",
+  "exifInfo"."colorspace" AS "exifInfo_colorspace",
+  "exifInfo"."bitsPerSample" AS "exifInfo_bitsPerSample",
+  "exifInfo"."fps" AS "exifInfo_fps",
+  "exifInfo"."exifTextSearchableColumn" AS "exifInfo_exifTextSearchableColumn"
+FROM
+  "assets" "entity"
+  LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "entity"."id"
+WHERE
+  (
+    "entity"."ownerId" = $1
+    AND "entity"."isVisible" = true
+    AND "entity"."isArchived" = false
+    AND "entity"."resizePath" IS NOT NULL
+    AND EXTRACT(
+      DAY
+      FROM
+        "entity"."localDateTime" AT TIME ZONE 'UTC'
+    ) = $2
+    AND EXTRACT(
+      MONTH
+      FROM
+        "entity"."localDateTime" AT TIME ZONE 'UTC'
+    ) = $3
+  )
+  AND ("entity"."deletedAt" IS NULL)
+ORDER BY
+  "entity"."localDateTime" DESC
+
+-- AssetRepository.getByIds
+SELECT
+  "AssetEntity"."id" AS "AssetEntity_id",
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+  "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+  "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+  "AssetEntity"."type" AS "AssetEntity_type",
+  "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+  "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+  "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+  "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+  "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+  "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+  "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+  "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+  "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+  "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+  "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+  "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+  "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+  "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+  "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+  "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+  "AssetEntity"."checksum" AS "AssetEntity_checksum",
+  "AssetEntity"."duration" AS "AssetEntity_duration",
+  "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+  "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+  "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+  "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+  "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId",
+  "AssetEntity__AssetEntity_exifInfo"."assetId" AS "AssetEntity__AssetEntity_exifInfo_assetId",
+  "AssetEntity__AssetEntity_exifInfo"."description" AS "AssetEntity__AssetEntity_exifInfo_description",
+  "AssetEntity__AssetEntity_exifInfo"."exifImageWidth" AS "AssetEntity__AssetEntity_exifInfo_exifImageWidth",
+  "AssetEntity__AssetEntity_exifInfo"."exifImageHeight" AS "AssetEntity__AssetEntity_exifInfo_exifImageHeight",
+  "AssetEntity__AssetEntity_exifInfo"."fileSizeInByte" AS "AssetEntity__AssetEntity_exifInfo_fileSizeInByte",
+  "AssetEntity__AssetEntity_exifInfo"."orientation" AS "AssetEntity__AssetEntity_exifInfo_orientation",
+  "AssetEntity__AssetEntity_exifInfo"."dateTimeOriginal" AS "AssetEntity__AssetEntity_exifInfo_dateTimeOriginal",
+  "AssetEntity__AssetEntity_exifInfo"."modifyDate" AS "AssetEntity__AssetEntity_exifInfo_modifyDate",
+  "AssetEntity__AssetEntity_exifInfo"."timeZone" AS "AssetEntity__AssetEntity_exifInfo_timeZone",
+  "AssetEntity__AssetEntity_exifInfo"."latitude" AS "AssetEntity__AssetEntity_exifInfo_latitude",
+  "AssetEntity__AssetEntity_exifInfo"."longitude" AS "AssetEntity__AssetEntity_exifInfo_longitude",
+  "AssetEntity__AssetEntity_exifInfo"."projectionType" AS "AssetEntity__AssetEntity_exifInfo_projectionType",
+  "AssetEntity__AssetEntity_exifInfo"."city" AS "AssetEntity__AssetEntity_exifInfo_city",
+  "AssetEntity__AssetEntity_exifInfo"."livePhotoCID" AS "AssetEntity__AssetEntity_exifInfo_livePhotoCID",
+  "AssetEntity__AssetEntity_exifInfo"."state" AS "AssetEntity__AssetEntity_exifInfo_state",
+  "AssetEntity__AssetEntity_exifInfo"."country" AS "AssetEntity__AssetEntity_exifInfo_country",
+  "AssetEntity__AssetEntity_exifInfo"."make" AS "AssetEntity__AssetEntity_exifInfo_make",
+  "AssetEntity__AssetEntity_exifInfo"."model" AS "AssetEntity__AssetEntity_exifInfo_model",
+  "AssetEntity__AssetEntity_exifInfo"."lensModel" AS "AssetEntity__AssetEntity_exifInfo_lensModel",
+  "AssetEntity__AssetEntity_exifInfo"."fNumber" AS "AssetEntity__AssetEntity_exifInfo_fNumber",
+  "AssetEntity__AssetEntity_exifInfo"."focalLength" AS "AssetEntity__AssetEntity_exifInfo_focalLength",
+  "AssetEntity__AssetEntity_exifInfo"."iso" AS "AssetEntity__AssetEntity_exifInfo_iso",
+  "AssetEntity__AssetEntity_exifInfo"."exposureTime" AS "AssetEntity__AssetEntity_exifInfo_exposureTime",
+  "AssetEntity__AssetEntity_exifInfo"."profileDescription" AS "AssetEntity__AssetEntity_exifInfo_profileDescription",
+  "AssetEntity__AssetEntity_exifInfo"."colorspace" AS "AssetEntity__AssetEntity_exifInfo_colorspace",
+  "AssetEntity__AssetEntity_exifInfo"."bitsPerSample" AS "AssetEntity__AssetEntity_exifInfo_bitsPerSample",
+  "AssetEntity__AssetEntity_exifInfo"."fps" AS "AssetEntity__AssetEntity_exifInfo_fps",
+  "AssetEntity__AssetEntity_exifInfo"."exifTextSearchableColumn" AS "AssetEntity__AssetEntity_exifInfo_exifTextSearchableColumn",
+  "AssetEntity__AssetEntity_smartInfo"."assetId" AS "AssetEntity__AssetEntity_smartInfo_assetId",
+  "AssetEntity__AssetEntity_smartInfo"."tags" AS "AssetEntity__AssetEntity_smartInfo_tags",
+  "AssetEntity__AssetEntity_smartInfo"."objects" AS "AssetEntity__AssetEntity_smartInfo_objects",
+  "AssetEntity__AssetEntity_smartInfo"."clipEmbedding" AS "AssetEntity__AssetEntity_smartInfo_clipEmbedding",
+  "AssetEntity__AssetEntity_tags"."id" AS "AssetEntity__AssetEntity_tags_id",
+  "AssetEntity__AssetEntity_tags"."type" AS "AssetEntity__AssetEntity_tags_type",
+  "AssetEntity__AssetEntity_tags"."name" AS "AssetEntity__AssetEntity_tags_name",
+  "AssetEntity__AssetEntity_tags"."userId" AS "AssetEntity__AssetEntity_tags_userId",
+  "AssetEntity__AssetEntity_tags"."renameTagId" AS "AssetEntity__AssetEntity_tags_renameTagId",
+  "AssetEntity__AssetEntity_faces"."id" AS "AssetEntity__AssetEntity_faces_id",
+  "AssetEntity__AssetEntity_faces"."assetId" AS "AssetEntity__AssetEntity_faces_assetId",
+  "AssetEntity__AssetEntity_faces"."personId" AS "AssetEntity__AssetEntity_faces_personId",
+  "AssetEntity__AssetEntity_faces"."embedding" AS "AssetEntity__AssetEntity_faces_embedding",
+  "AssetEntity__AssetEntity_faces"."imageWidth" AS "AssetEntity__AssetEntity_faces_imageWidth",
+  "AssetEntity__AssetEntity_faces"."imageHeight" AS "AssetEntity__AssetEntity_faces_imageHeight",
+  "AssetEntity__AssetEntity_faces"."boundingBoxX1" AS "AssetEntity__AssetEntity_faces_boundingBoxX1",
+  "AssetEntity__AssetEntity_faces"."boundingBoxY1" AS "AssetEntity__AssetEntity_faces_boundingBoxY1",
+  "AssetEntity__AssetEntity_faces"."boundingBoxX2" AS "AssetEntity__AssetEntity_faces_boundingBoxX2",
+  "AssetEntity__AssetEntity_faces"."boundingBoxY2" AS "AssetEntity__AssetEntity_faces_boundingBoxY2",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_id",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."createdAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_createdAt",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."updatedAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_updatedAt",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."ownerId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_ownerId",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."name" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_name",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."birthDate" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_birthDate",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."thumbnailPath" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_thumbnailPath",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."faceAssetId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_faceAssetId",
+  "8258e303a73a72cf6abb13d73fb592dde0d68280"."isHidden" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_isHidden",
+  "AssetEntity__AssetEntity_stack"."id" AS "AssetEntity__AssetEntity_stack_id",
+  "AssetEntity__AssetEntity_stack"."deviceAssetId" AS "AssetEntity__AssetEntity_stack_deviceAssetId",
+  "AssetEntity__AssetEntity_stack"."ownerId" AS "AssetEntity__AssetEntity_stack_ownerId",
+  "AssetEntity__AssetEntity_stack"."libraryId" AS "AssetEntity__AssetEntity_stack_libraryId",
+  "AssetEntity__AssetEntity_stack"."deviceId" AS "AssetEntity__AssetEntity_stack_deviceId",
+  "AssetEntity__AssetEntity_stack"."type" AS "AssetEntity__AssetEntity_stack_type",
+  "AssetEntity__AssetEntity_stack"."originalPath" AS "AssetEntity__AssetEntity_stack_originalPath",
+  "AssetEntity__AssetEntity_stack"."resizePath" AS "AssetEntity__AssetEntity_stack_resizePath",
+  "AssetEntity__AssetEntity_stack"."webpPath" AS "AssetEntity__AssetEntity_stack_webpPath",
+  "AssetEntity__AssetEntity_stack"."thumbhash" AS "AssetEntity__AssetEntity_stack_thumbhash",
+  "AssetEntity__AssetEntity_stack"."encodedVideoPath" AS "AssetEntity__AssetEntity_stack_encodedVideoPath",
+  "AssetEntity__AssetEntity_stack"."createdAt" AS "AssetEntity__AssetEntity_stack_createdAt",
+  "AssetEntity__AssetEntity_stack"."updatedAt" AS "AssetEntity__AssetEntity_stack_updatedAt",
+  "AssetEntity__AssetEntity_stack"."deletedAt" AS "AssetEntity__AssetEntity_stack_deletedAt",
+  "AssetEntity__AssetEntity_stack"."fileCreatedAt" AS "AssetEntity__AssetEntity_stack_fileCreatedAt",
+  "AssetEntity__AssetEntity_stack"."localDateTime" AS "AssetEntity__AssetEntity_stack_localDateTime",
+  "AssetEntity__AssetEntity_stack"."fileModifiedAt" AS "AssetEntity__AssetEntity_stack_fileModifiedAt",
+  "AssetEntity__AssetEntity_stack"."isFavorite" AS "AssetEntity__AssetEntity_stack_isFavorite",
+  "AssetEntity__AssetEntity_stack"."isArchived" AS "AssetEntity__AssetEntity_stack_isArchived",
+  "AssetEntity__AssetEntity_stack"."isExternal" AS "AssetEntity__AssetEntity_stack_isExternal",
+  "AssetEntity__AssetEntity_stack"."isReadOnly" AS "AssetEntity__AssetEntity_stack_isReadOnly",
+  "AssetEntity__AssetEntity_stack"."isOffline" AS "AssetEntity__AssetEntity_stack_isOffline",
+  "AssetEntity__AssetEntity_stack"."checksum" AS "AssetEntity__AssetEntity_stack_checksum",
+  "AssetEntity__AssetEntity_stack"."duration" AS "AssetEntity__AssetEntity_stack_duration",
+  "AssetEntity__AssetEntity_stack"."isVisible" AS "AssetEntity__AssetEntity_stack_isVisible",
+  "AssetEntity__AssetEntity_stack"."livePhotoVideoId" AS "AssetEntity__AssetEntity_stack_livePhotoVideoId",
+  "AssetEntity__AssetEntity_stack"."originalFileName" AS "AssetEntity__AssetEntity_stack_originalFileName",
+  "AssetEntity__AssetEntity_stack"."sidecarPath" AS "AssetEntity__AssetEntity_stack_sidecarPath",
+  "AssetEntity__AssetEntity_stack"."stackParentId" AS "AssetEntity__AssetEntity_stack_stackParentId"
+FROM
+  "assets" "AssetEntity"
+  LEFT JOIN "exif" "AssetEntity__AssetEntity_exifInfo" ON "AssetEntity__AssetEntity_exifInfo"."assetId" = "AssetEntity"."id"
+  LEFT JOIN "smart_info" "AssetEntity__AssetEntity_smartInfo" ON "AssetEntity__AssetEntity_smartInfo"."assetId" = "AssetEntity"."id"
+  LEFT JOIN "tag_asset" "AssetEntity_AssetEntity__AssetEntity_tags" ON "AssetEntity_AssetEntity__AssetEntity_tags"."assetsId" = "AssetEntity"."id"
+  LEFT JOIN "tags" "AssetEntity__AssetEntity_tags" ON "AssetEntity__AssetEntity_tags"."id" = "AssetEntity_AssetEntity__AssetEntity_tags"."tagsId"
+  LEFT JOIN "asset_faces" "AssetEntity__AssetEntity_faces" ON "AssetEntity__AssetEntity_faces"."assetId" = "AssetEntity"."id"
+  LEFT JOIN "person" "8258e303a73a72cf6abb13d73fb592dde0d68280" ON "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" = "AssetEntity__AssetEntity_faces"."personId"
+  LEFT JOIN "assets" "AssetEntity__AssetEntity_stack" ON "AssetEntity__AssetEntity_stack"."stackParentId" = "AssetEntity"."id"
+WHERE
+  ("AssetEntity"."id" IN ($1))
+
+-- AssetRepository.deleteAll
+DELETE FROM "assets"
+WHERE
+  "ownerId" = $1
+
+-- AssetRepository.getByLibraryId
+SELECT
+  "AssetEntity"."id" AS "AssetEntity_id",
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+  "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+  "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+  "AssetEntity"."type" AS "AssetEntity_type",
+  "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+  "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+  "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+  "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+  "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+  "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+  "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+  "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+  "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+  "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+  "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+  "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+  "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+  "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+  "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+  "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+  "AssetEntity"."checksum" AS "AssetEntity_checksum",
+  "AssetEntity"."duration" AS "AssetEntity_duration",
+  "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+  "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+  "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+  "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+  "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId"
+FROM
+  "assets" "AssetEntity"
+  LEFT JOIN "libraries" "AssetEntity__AssetEntity_library" ON "AssetEntity__AssetEntity_library"."id" = "AssetEntity"."libraryId"
+  AND (
+    "AssetEntity__AssetEntity_library"."deletedAt" IS NULL
+  )
+WHERE
+  (("AssetEntity__AssetEntity_library"."id" IN ($1)))
+  AND ("AssetEntity"."deletedAt" IS NULL)
+
+-- AssetRepository.getByLibraryIdAndOriginalPath
+SELECT DISTINCT
+  "distinctAlias"."AssetEntity_id" AS "ids_AssetEntity_id"
+FROM
+  (
+    SELECT
+      "AssetEntity"."id" AS "AssetEntity_id",
+      "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+      "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+      "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+      "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+      "AssetEntity"."type" AS "AssetEntity_type",
+      "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+      "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+      "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+      "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+      "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+      "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+      "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+      "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+      "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+      "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+      "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+      "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+      "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+      "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+      "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+      "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+      "AssetEntity"."checksum" AS "AssetEntity_checksum",
+      "AssetEntity"."duration" AS "AssetEntity_duration",
+      "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+      "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+      "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+      "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+      "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId"
+    FROM
+      "assets" "AssetEntity"
+      LEFT JOIN "libraries" "AssetEntity__AssetEntity_library" ON "AssetEntity__AssetEntity_library"."id" = "AssetEntity"."libraryId"
+      AND (
+        "AssetEntity__AssetEntity_library"."deletedAt" IS NULL
+      )
+    WHERE
+      (
+        (
+          "AssetEntity__AssetEntity_library"."id" = $1
+          AND "AssetEntity"."originalPath" = $2
+        )
+      )
+      AND ("AssetEntity"."deletedAt" IS NULL)
+  ) "distinctAlias"
+ORDER BY
+  "AssetEntity_id" ASC
+LIMIT
+  1
+
+-- AssetRepository.getAllByDeviceId
+SELECT
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."id" AS "AssetEntity_id"
+FROM
+  "assets" "AssetEntity"
+WHERE
+  (
+    "AssetEntity"."ownerId" = $1
+    AND "AssetEntity"."deviceId" = $2
+    AND "AssetEntity"."isVisible" = $3
+  )
+
+-- AssetRepository.getById
+SELECT DISTINCT
+  "distinctAlias"."AssetEntity_id" AS "ids_AssetEntity_id"
+FROM
+  (
+    SELECT
+      "AssetEntity"."id" AS "AssetEntity_id",
+      "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+      "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+      "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+      "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+      "AssetEntity"."type" AS "AssetEntity_type",
+      "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+      "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+      "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+      "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+      "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+      "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+      "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+      "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+      "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+      "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+      "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+      "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+      "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+      "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+      "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+      "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+      "AssetEntity"."checksum" AS "AssetEntity_checksum",
+      "AssetEntity"."duration" AS "AssetEntity_duration",
+      "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+      "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+      "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+      "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+      "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId",
+      "AssetEntity__AssetEntity_faces"."id" AS "AssetEntity__AssetEntity_faces_id",
+      "AssetEntity__AssetEntity_faces"."assetId" AS "AssetEntity__AssetEntity_faces_assetId",
+      "AssetEntity__AssetEntity_faces"."personId" AS "AssetEntity__AssetEntity_faces_personId",
+      "AssetEntity__AssetEntity_faces"."embedding" AS "AssetEntity__AssetEntity_faces_embedding",
+      "AssetEntity__AssetEntity_faces"."imageWidth" AS "AssetEntity__AssetEntity_faces_imageWidth",
+      "AssetEntity__AssetEntity_faces"."imageHeight" AS "AssetEntity__AssetEntity_faces_imageHeight",
+      "AssetEntity__AssetEntity_faces"."boundingBoxX1" AS "AssetEntity__AssetEntity_faces_boundingBoxX1",
+      "AssetEntity__AssetEntity_faces"."boundingBoxY1" AS "AssetEntity__AssetEntity_faces_boundingBoxY1",
+      "AssetEntity__AssetEntity_faces"."boundingBoxX2" AS "AssetEntity__AssetEntity_faces_boundingBoxX2",
+      "AssetEntity__AssetEntity_faces"."boundingBoxY2" AS "AssetEntity__AssetEntity_faces_boundingBoxY2",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_id",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."createdAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_createdAt",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."updatedAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_updatedAt",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."ownerId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_ownerId",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."name" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_name",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."birthDate" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_birthDate",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."thumbnailPath" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_thumbnailPath",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."faceAssetId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_faceAssetId",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."isHidden" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_isHidden",
+      "AssetEntity__AssetEntity_library"."id" AS "AssetEntity__AssetEntity_library_id",
+      "AssetEntity__AssetEntity_library"."name" AS "AssetEntity__AssetEntity_library_name",
+      "AssetEntity__AssetEntity_library"."ownerId" AS "AssetEntity__AssetEntity_library_ownerId",
+      "AssetEntity__AssetEntity_library"."type" AS "AssetEntity__AssetEntity_library_type",
+      "AssetEntity__AssetEntity_library"."importPaths" AS "AssetEntity__AssetEntity_library_importPaths",
+      "AssetEntity__AssetEntity_library"."exclusionPatterns" AS "AssetEntity__AssetEntity_library_exclusionPatterns",
+      "AssetEntity__AssetEntity_library"."createdAt" AS "AssetEntity__AssetEntity_library_createdAt",
+      "AssetEntity__AssetEntity_library"."updatedAt" AS "AssetEntity__AssetEntity_library_updatedAt",
+      "AssetEntity__AssetEntity_library"."deletedAt" AS "AssetEntity__AssetEntity_library_deletedAt",
+      "AssetEntity__AssetEntity_library"."refreshedAt" AS "AssetEntity__AssetEntity_library_refreshedAt",
+      "AssetEntity__AssetEntity_library"."isVisible" AS "AssetEntity__AssetEntity_library_isVisible",
+      "AssetEntity__AssetEntity_stack"."id" AS "AssetEntity__AssetEntity_stack_id",
+      "AssetEntity__AssetEntity_stack"."deviceAssetId" AS "AssetEntity__AssetEntity_stack_deviceAssetId",
+      "AssetEntity__AssetEntity_stack"."ownerId" AS "AssetEntity__AssetEntity_stack_ownerId",
+      "AssetEntity__AssetEntity_stack"."libraryId" AS "AssetEntity__AssetEntity_stack_libraryId",
+      "AssetEntity__AssetEntity_stack"."deviceId" AS "AssetEntity__AssetEntity_stack_deviceId",
+      "AssetEntity__AssetEntity_stack"."type" AS "AssetEntity__AssetEntity_stack_type",
+      "AssetEntity__AssetEntity_stack"."originalPath" AS "AssetEntity__AssetEntity_stack_originalPath",
+      "AssetEntity__AssetEntity_stack"."resizePath" AS "AssetEntity__AssetEntity_stack_resizePath",
+      "AssetEntity__AssetEntity_stack"."webpPath" AS "AssetEntity__AssetEntity_stack_webpPath",
+      "AssetEntity__AssetEntity_stack"."thumbhash" AS "AssetEntity__AssetEntity_stack_thumbhash",
+      "AssetEntity__AssetEntity_stack"."encodedVideoPath" AS "AssetEntity__AssetEntity_stack_encodedVideoPath",
+      "AssetEntity__AssetEntity_stack"."createdAt" AS "AssetEntity__AssetEntity_stack_createdAt",
+      "AssetEntity__AssetEntity_stack"."updatedAt" AS "AssetEntity__AssetEntity_stack_updatedAt",
+      "AssetEntity__AssetEntity_stack"."deletedAt" AS "AssetEntity__AssetEntity_stack_deletedAt",
+      "AssetEntity__AssetEntity_stack"."fileCreatedAt" AS "AssetEntity__AssetEntity_stack_fileCreatedAt",
+      "AssetEntity__AssetEntity_stack"."localDateTime" AS "AssetEntity__AssetEntity_stack_localDateTime",
+      "AssetEntity__AssetEntity_stack"."fileModifiedAt" AS "AssetEntity__AssetEntity_stack_fileModifiedAt",
+      "AssetEntity__AssetEntity_stack"."isFavorite" AS "AssetEntity__AssetEntity_stack_isFavorite",
+      "AssetEntity__AssetEntity_stack"."isArchived" AS "AssetEntity__AssetEntity_stack_isArchived",
+      "AssetEntity__AssetEntity_stack"."isExternal" AS "AssetEntity__AssetEntity_stack_isExternal",
+      "AssetEntity__AssetEntity_stack"."isReadOnly" AS "AssetEntity__AssetEntity_stack_isReadOnly",
+      "AssetEntity__AssetEntity_stack"."isOffline" AS "AssetEntity__AssetEntity_stack_isOffline",
+      "AssetEntity__AssetEntity_stack"."checksum" AS "AssetEntity__AssetEntity_stack_checksum",
+      "AssetEntity__AssetEntity_stack"."duration" AS "AssetEntity__AssetEntity_stack_duration",
+      "AssetEntity__AssetEntity_stack"."isVisible" AS "AssetEntity__AssetEntity_stack_isVisible",
+      "AssetEntity__AssetEntity_stack"."livePhotoVideoId" AS "AssetEntity__AssetEntity_stack_livePhotoVideoId",
+      "AssetEntity__AssetEntity_stack"."originalFileName" AS "AssetEntity__AssetEntity_stack_originalFileName",
+      "AssetEntity__AssetEntity_stack"."sidecarPath" AS "AssetEntity__AssetEntity_stack_sidecarPath",
+      "AssetEntity__AssetEntity_stack"."stackParentId" AS "AssetEntity__AssetEntity_stack_stackParentId"
+    FROM
+      "assets" "AssetEntity"
+      LEFT JOIN "asset_faces" "AssetEntity__AssetEntity_faces" ON "AssetEntity__AssetEntity_faces"."assetId" = "AssetEntity"."id"
+      LEFT JOIN "person" "8258e303a73a72cf6abb13d73fb592dde0d68280" ON "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" = "AssetEntity__AssetEntity_faces"."personId"
+      LEFT JOIN "libraries" "AssetEntity__AssetEntity_library" ON "AssetEntity__AssetEntity_library"."id" = "AssetEntity"."libraryId"
+      LEFT JOIN "assets" "AssetEntity__AssetEntity_stack" ON "AssetEntity__AssetEntity_stack"."stackParentId" = "AssetEntity"."id"
+    WHERE
+      ("AssetEntity"."id" = $1)
+  ) "distinctAlias"
+ORDER BY
+  "AssetEntity_id" ASC
+LIMIT
+  1
+
+-- AssetRepository.updateAll
+UPDATE "assets"
+SET
+  "deviceId" = $1,
+  "updatedAt" = CURRENT_TIMESTAMP
+WHERE
+  "id" IN ($2)
+
+-- AssetRepository.getByChecksum
+SELECT
+  "AssetEntity"."id" AS "AssetEntity_id",
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+  "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+  "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+  "AssetEntity"."type" AS "AssetEntity_type",
+  "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+  "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+  "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+  "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+  "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+  "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+  "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+  "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+  "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+  "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+  "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+  "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+  "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+  "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+  "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+  "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+  "AssetEntity"."checksum" AS "AssetEntity_checksum",
+  "AssetEntity"."duration" AS "AssetEntity_duration",
+  "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+  "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+  "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+  "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+  "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId"
+FROM
+  "assets" "AssetEntity"
+WHERE
+  (
+    (
+      "AssetEntity"."ownerId" = $1
+      AND "AssetEntity"."checksum" = $2
+    )
+  )
+  AND ("AssetEntity"."deletedAt" IS NULL)
+LIMIT
+  1
+
+-- AssetRepository.getWithout (sidecar)
+SELECT
+  "AssetEntity"."id" AS "AssetEntity_id",
+  "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+  "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+  "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+  "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+  "AssetEntity"."type" AS "AssetEntity_type",
+  "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+  "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+  "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+  "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+  "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+  "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+  "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+  "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+  "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+  "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+  "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+  "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+  "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+  "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+  "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+  "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+  "AssetEntity"."checksum" AS "AssetEntity_checksum",
+  "AssetEntity"."duration" AS "AssetEntity_duration",
+  "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+  "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+  "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+  "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+  "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId"
+FROM
+  "assets" "AssetEntity"
+WHERE
+  (
+    (
+      (
+        "AssetEntity"."sidecarPath" IS NULL
+        AND "AssetEntity"."isVisible" = $1
+      )
+      OR (
+        "AssetEntity"."sidecarPath" = $2
+        AND "AssetEntity"."isVisible" = $3
+      )
+    )
+  )
+  AND ("AssetEntity"."deletedAt" IS NULL)
+ORDER BY
+  "AssetEntity"."createdAt" ASC
+LIMIT
+  11
diff --git a/server/src/infra/sql/audit.repository.sql b/server/src/infra/sql/audit.repository.sql
new file mode 100644
index 000000000..21f9f116b
--- /dev/null
+++ b/server/src/infra/sql/audit.repository.sql
@@ -0,0 +1 @@
+-- NOTE: This file is auto generated by ./sql-generator
diff --git a/server/src/infra/sql/library.repository.sql b/server/src/infra/sql/library.repository.sql
new file mode 100644
index 000000000..44e6ddcc9
--- /dev/null
+++ b/server/src/infra/sql/library.repository.sql
@@ -0,0 +1,299 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- LibraryRepository.get
+SELECT DISTINCT
+  "distinctAlias"."LibraryEntity_id" AS "ids_LibraryEntity_id"
+FROM
+  (
+    SELECT
+      "LibraryEntity"."id" AS "LibraryEntity_id",
+      "LibraryEntity"."name" AS "LibraryEntity_name",
+      "LibraryEntity"."ownerId" AS "LibraryEntity_ownerId",
+      "LibraryEntity"."type" AS "LibraryEntity_type",
+      "LibraryEntity"."importPaths" AS "LibraryEntity_importPaths",
+      "LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns",
+      "LibraryEntity"."createdAt" AS "LibraryEntity_createdAt",
+      "LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt",
+      "LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt",
+      "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt",
+      "LibraryEntity"."isVisible" AS "LibraryEntity_isVisible",
+      "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id",
+      "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name",
+      "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor",
+      "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin",
+      "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email",
+      "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel",
+      "LibraryEntity__LibraryEntity_owner"."externalPath" AS "LibraryEntity__LibraryEntity_owner_externalPath",
+      "LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId",
+      "LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath",
+      "LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword",
+      "LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt",
+      "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt",
+      "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt",
+      "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled"
+    FROM
+      "libraries" "LibraryEntity"
+      LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId"
+      AND (
+        "LibraryEntity__LibraryEntity_owner"."deletedAt" IS NULL
+      )
+    WHERE
+      (("LibraryEntity"."id" = $1))
+      AND ("LibraryEntity"."deletedAt" IS NULL)
+  ) "distinctAlias"
+ORDER BY
+  "LibraryEntity_id" ASC
+LIMIT
+  1
+
+-- LibraryRepository.existsByName
+SELECT
+  1 AS "row_exists"
+FROM
+  (
+    SELECT
+      1 AS dummy_column
+  ) "dummy_table"
+WHERE
+  EXISTS (
+    SELECT
+      1
+    FROM
+      "libraries" "LibraryEntity"
+    WHERE
+      (("LibraryEntity"."name" = $1))
+      AND ("LibraryEntity"."deletedAt" IS NULL)
+  )
+LIMIT
+  1
+
+-- LibraryRepository.getCountForUser
+SELECT
+  COUNT(1) AS "cnt"
+FROM
+  "libraries" "LibraryEntity"
+WHERE
+  (("LibraryEntity"."ownerId" = $1))
+  AND ("LibraryEntity"."deletedAt" IS NULL)
+
+-- LibraryRepository.getDefaultUploadLibrary
+SELECT
+  "LibraryEntity"."id" AS "LibraryEntity_id",
+  "LibraryEntity"."name" AS "LibraryEntity_name",
+  "LibraryEntity"."ownerId" AS "LibraryEntity_ownerId",
+  "LibraryEntity"."type" AS "LibraryEntity_type",
+  "LibraryEntity"."importPaths" AS "LibraryEntity_importPaths",
+  "LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns",
+  "LibraryEntity"."createdAt" AS "LibraryEntity_createdAt",
+  "LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt",
+  "LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt",
+  "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt",
+  "LibraryEntity"."isVisible" AS "LibraryEntity_isVisible"
+FROM
+  "libraries" "LibraryEntity"
+WHERE
+  (
+    (
+      "LibraryEntity"."ownerId" = $1
+      AND "LibraryEntity"."type" = $2
+    )
+  )
+  AND ("LibraryEntity"."deletedAt" IS NULL)
+ORDER BY
+  "LibraryEntity"."createdAt" ASC
+LIMIT
+  1
+
+-- LibraryRepository.getUploadLibraryCount
+SELECT
+  COUNT(1) AS "cnt"
+FROM
+  "libraries" "LibraryEntity"
+WHERE
+  (
+    (
+      "LibraryEntity"."ownerId" = $1
+      AND "LibraryEntity"."type" = $2
+    )
+  )
+  AND ("LibraryEntity"."deletedAt" IS NULL)
+
+-- LibraryRepository.getAllByUserId
+SELECT
+  "LibraryEntity"."id" AS "LibraryEntity_id",
+  "LibraryEntity"."name" AS "LibraryEntity_name",
+  "LibraryEntity"."ownerId" AS "LibraryEntity_ownerId",
+  "LibraryEntity"."type" AS "LibraryEntity_type",
+  "LibraryEntity"."importPaths" AS "LibraryEntity_importPaths",
+  "LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns",
+  "LibraryEntity"."createdAt" AS "LibraryEntity_createdAt",
+  "LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt",
+  "LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt",
+  "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt",
+  "LibraryEntity"."isVisible" AS "LibraryEntity_isVisible",
+  "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id",
+  "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name",
+  "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor",
+  "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin",
+  "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email",
+  "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel",
+  "LibraryEntity__LibraryEntity_owner"."externalPath" AS "LibraryEntity__LibraryEntity_owner_externalPath",
+  "LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId",
+  "LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath",
+  "LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword",
+  "LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt",
+  "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt",
+  "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt",
+  "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled"
+FROM
+  "libraries" "LibraryEntity"
+  LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId"
+  AND (
+    "LibraryEntity__LibraryEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  (
+    (
+      "LibraryEntity"."ownerId" = $1
+      AND "LibraryEntity"."isVisible" = $2
+    )
+  )
+  AND ("LibraryEntity"."deletedAt" IS NULL)
+ORDER BY
+  "LibraryEntity"."createdAt" ASC
+
+-- LibraryRepository.getAll
+SELECT
+  "LibraryEntity"."id" AS "LibraryEntity_id",
+  "LibraryEntity"."name" AS "LibraryEntity_name",
+  "LibraryEntity"."ownerId" AS "LibraryEntity_ownerId",
+  "LibraryEntity"."type" AS "LibraryEntity_type",
+  "LibraryEntity"."importPaths" AS "LibraryEntity_importPaths",
+  "LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns",
+  "LibraryEntity"."createdAt" AS "LibraryEntity_createdAt",
+  "LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt",
+  "LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt",
+  "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt",
+  "LibraryEntity"."isVisible" AS "LibraryEntity_isVisible",
+  "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id",
+  "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name",
+  "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor",
+  "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin",
+  "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email",
+  "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel",
+  "LibraryEntity__LibraryEntity_owner"."externalPath" AS "LibraryEntity__LibraryEntity_owner_externalPath",
+  "LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId",
+  "LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath",
+  "LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword",
+  "LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt",
+  "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt",
+  "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt",
+  "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled"
+FROM
+  "libraries" "LibraryEntity"
+  LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId"
+  AND (
+    "LibraryEntity__LibraryEntity_owner"."deletedAt" IS NULL
+  )
+WHERE
+  "LibraryEntity"."deletedAt" IS NULL
+ORDER BY
+  "LibraryEntity"."createdAt" ASC
+
+-- LibraryRepository.getAllDeleted
+SELECT
+  "LibraryEntity"."id" AS "LibraryEntity_id",
+  "LibraryEntity"."name" AS "LibraryEntity_name",
+  "LibraryEntity"."ownerId" AS "LibraryEntity_ownerId",
+  "LibraryEntity"."type" AS "LibraryEntity_type",
+  "LibraryEntity"."importPaths" AS "LibraryEntity_importPaths",
+  "LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns",
+  "LibraryEntity"."createdAt" AS "LibraryEntity_createdAt",
+  "LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt",
+  "LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt",
+  "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt",
+  "LibraryEntity"."isVisible" AS "LibraryEntity_isVisible",
+  "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id",
+  "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name",
+  "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor",
+  "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin",
+  "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email",
+  "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel",
+  "LibraryEntity__LibraryEntity_owner"."externalPath" AS "LibraryEntity__LibraryEntity_owner_externalPath",
+  "LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId",
+  "LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath",
+  "LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword",
+  "LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt",
+  "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt",
+  "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt",
+  "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled"
+FROM
+  "libraries" "LibraryEntity"
+  LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId"
+WHERE
+  (
+    "LibraryEntity"."isVisible" = $1
+    AND NOT ("LibraryEntity"."deletedAt" IS NULL)
+  )
+ORDER BY
+  "LibraryEntity"."createdAt" ASC
+
+-- LibraryRepository.getStatistics
+SELECT
+  "libraries"."id" AS "libraries_id",
+  "libraries"."name" AS "libraries_name",
+  "libraries"."ownerId" AS "libraries_ownerId",
+  "libraries"."type" AS "libraries_type",
+  "libraries"."importPaths" AS "libraries_importPaths",
+  "libraries"."exclusionPatterns" AS "libraries_exclusionPatterns",
+  "libraries"."createdAt" AS "libraries_createdAt",
+  "libraries"."updatedAt" AS "libraries_updatedAt",
+  "libraries"."deletedAt" AS "libraries_deletedAt",
+  "libraries"."refreshedAt" AS "libraries_refreshedAt",
+  "libraries"."isVisible" AS "libraries_isVisible",
+  COUNT("assets"."id") FILTER (
+    WHERE
+      "assets"."type" = 'IMAGE'
+      AND "assets"."isVisible"
+  ) AS "photos",
+  COUNT("assets"."id") FILTER (
+    WHERE
+      "assets"."type" = 'VIDEO'
+      AND "assets"."isVisible"
+  ) AS "videos",
+  COALESCE(SUM("exif"."fileSizeInByte"), 0) AS "usage"
+FROM
+  "libraries" "libraries"
+  LEFT JOIN "assets" "assets" ON "assets"."libraryId" = "libraries"."id"
+  AND ("assets"."deletedAt" IS NULL)
+  LEFT JOIN "exif" "exif" ON "exif"."assetId" = "assets"."id"
+WHERE
+  ("libraries"."id" = $1)
+  AND ("libraries"."deletedAt" IS NULL)
+GROUP BY
+  "libraries"."id"
+
+-- LibraryRepository.getOnlineAssetPaths
+SELECT
+  "assets"."originalPath" AS "assets_originalPath"
+FROM
+  "libraries" "library"
+  INNER JOIN "assets" "assets" ON "assets"."libraryId" = "library"."id"
+  AND ("assets"."deletedAt" IS NULL)
+WHERE
+  (
+    "library"."id" = $1
+    AND "assets"."isOffline" = false
+  )
+  AND ("library"."deletedAt" IS NULL)
+
+-- LibraryRepository.getAssetIds
+SELECT
+  "assets"."id" AS "assets_id"
+FROM
+  "libraries" "library"
+  INNER JOIN "assets" "assets" ON "assets"."libraryId" = "library"."id"
+  AND ("assets"."deletedAt" IS NULL)
+WHERE
+  ("library"."id" = $1)
+  AND ("library"."deletedAt" IS NULL)
diff --git a/server/src/infra/sql/move.repository.sql b/server/src/infra/sql/move.repository.sql
new file mode 100644
index 000000000..b83175bd3
--- /dev/null
+++ b/server/src/infra/sql/move.repository.sql
@@ -0,0 +1,18 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- MoveRepository.getByEntity
+SELECT
+  "MoveEntity"."id" AS "MoveEntity_id",
+  "MoveEntity"."entityId" AS "MoveEntity_entityId",
+  "MoveEntity"."pathType" AS "MoveEntity_pathType",
+  "MoveEntity"."oldPath" AS "MoveEntity_oldPath",
+  "MoveEntity"."newPath" AS "MoveEntity_newPath"
+FROM
+  "move_history" "MoveEntity"
+WHERE
+  (
+    "MoveEntity"."entityId" = $1
+    AND "MoveEntity"."pathType" = $2
+  )
+LIMIT
+  1
diff --git a/server/src/infra/sql/partner.repository.sql b/server/src/infra/sql/partner.repository.sql
new file mode 100644
index 000000000..21f9f116b
--- /dev/null
+++ b/server/src/infra/sql/partner.repository.sql
@@ -0,0 +1 @@
+-- NOTE: This file is auto generated by ./sql-generator
diff --git a/server/src/infra/sql/person.repository.sql b/server/src/infra/sql/person.repository.sql
new file mode 100644
index 000000000..933283746
--- /dev/null
+++ b/server/src/infra/sql/person.repository.sql
@@ -0,0 +1,367 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- PersonRepository.reassignFaces
+UPDATE "asset_faces"
+SET
+  "personId" = $1
+WHERE
+  "personId" = $2
+
+-- PersonRepository.getAllFaces
+SELECT
+  "AssetFaceEntity"."id" AS "AssetFaceEntity_id",
+  "AssetFaceEntity"."assetId" AS "AssetFaceEntity_assetId",
+  "AssetFaceEntity"."personId" AS "AssetFaceEntity_personId",
+  "AssetFaceEntity"."embedding" AS "AssetFaceEntity_embedding",
+  "AssetFaceEntity"."imageWidth" AS "AssetFaceEntity_imageWidth",
+  "AssetFaceEntity"."imageHeight" AS "AssetFaceEntity_imageHeight",
+  "AssetFaceEntity"."boundingBoxX1" AS "AssetFaceEntity_boundingBoxX1",
+  "AssetFaceEntity"."boundingBoxY1" AS "AssetFaceEntity_boundingBoxY1",
+  "AssetFaceEntity"."boundingBoxX2" AS "AssetFaceEntity_boundingBoxX2",
+  "AssetFaceEntity"."boundingBoxY2" AS "AssetFaceEntity_boundingBoxY2",
+  "AssetFaceEntity__AssetFaceEntity_asset"."id" AS "AssetFaceEntity__AssetFaceEntity_asset_id",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deviceAssetId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceAssetId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."ownerId" AS "AssetFaceEntity__AssetFaceEntity_asset_ownerId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."libraryId" AS "AssetFaceEntity__AssetFaceEntity_asset_libraryId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
+  "AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
+  "AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."updatedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_updatedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deletedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_deletedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."fileCreatedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_fileCreatedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."localDateTime" AS "AssetFaceEntity__AssetFaceEntity_asset_localDateTime",
+  "AssetFaceEntity__AssetFaceEntity_asset"."fileModifiedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_fileModifiedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isReadOnly" AS "AssetFaceEntity__AssetFaceEntity_asset_isReadOnly",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline",
+  "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum",
+  "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isVisible" AS "AssetFaceEntity__AssetFaceEntity_asset_isVisible",
+  "AssetFaceEntity__AssetFaceEntity_asset"."livePhotoVideoId" AS "AssetFaceEntity__AssetFaceEntity_asset_livePhotoVideoId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."originalFileName" AS "AssetFaceEntity__AssetFaceEntity_asset_originalFileName",
+  "AssetFaceEntity__AssetFaceEntity_asset"."sidecarPath" AS "AssetFaceEntity__AssetFaceEntity_asset_sidecarPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."stackParentId" AS "AssetFaceEntity__AssetFaceEntity_asset_stackParentId"
+FROM
+  "asset_faces" "AssetFaceEntity"
+  LEFT JOIN "assets" "AssetFaceEntity__AssetFaceEntity_asset" ON "AssetFaceEntity__AssetFaceEntity_asset"."id" = "AssetFaceEntity"."assetId"
+
+-- PersonRepository.getAll
+SELECT
+  "PersonEntity"."id" AS "PersonEntity_id",
+  "PersonEntity"."createdAt" AS "PersonEntity_createdAt",
+  "PersonEntity"."updatedAt" AS "PersonEntity_updatedAt",
+  "PersonEntity"."ownerId" AS "PersonEntity_ownerId",
+  "PersonEntity"."name" AS "PersonEntity_name",
+  "PersonEntity"."birthDate" AS "PersonEntity_birthDate",
+  "PersonEntity"."thumbnailPath" AS "PersonEntity_thumbnailPath",
+  "PersonEntity"."faceAssetId" AS "PersonEntity_faceAssetId",
+  "PersonEntity"."isHidden" AS "PersonEntity_isHidden"
+FROM
+  "person" "PersonEntity"
+
+-- PersonRepository.getAllWithoutThumbnail
+SELECT
+  "PersonEntity"."id" AS "PersonEntity_id",
+  "PersonEntity"."createdAt" AS "PersonEntity_createdAt",
+  "PersonEntity"."updatedAt" AS "PersonEntity_updatedAt",
+  "PersonEntity"."ownerId" AS "PersonEntity_ownerId",
+  "PersonEntity"."name" AS "PersonEntity_name",
+  "PersonEntity"."birthDate" AS "PersonEntity_birthDate",
+  "PersonEntity"."thumbnailPath" AS "PersonEntity_thumbnailPath",
+  "PersonEntity"."faceAssetId" AS "PersonEntity_faceAssetId",
+  "PersonEntity"."isHidden" AS "PersonEntity_isHidden"
+FROM
+  "person" "PersonEntity"
+WHERE
+  ("PersonEntity"."thumbnailPath" = $1)
+
+-- PersonRepository.getAllForUser
+SELECT
+  "person"."id" AS "person_id",
+  "person"."createdAt" AS "person_createdAt",
+  "person"."updatedAt" AS "person_updatedAt",
+  "person"."ownerId" AS "person_ownerId",
+  "person"."name" AS "person_name",
+  "person"."birthDate" AS "person_birthDate",
+  "person"."thumbnailPath" AS "person_thumbnailPath",
+  "person"."faceAssetId" AS "person_faceAssetId",
+  "person"."isHidden" AS "person_isHidden"
+FROM
+  "person" "person"
+  LEFT JOIN "asset_faces" "face" ON "face"."personId" = "person"."id"
+  INNER JOIN "assets" "asset" ON "asset"."id" = "face"."assetId"
+  AND ("asset"."deletedAt" IS NULL)
+WHERE
+  "person"."ownerId" = $1
+  AND "person"."isHidden" = false
+GROUP BY
+  "person"."id"
+HAVING
+  "person"."name" != ''
+  OR COUNT("face"."assetId") >= $2
+ORDER BY
+  "person"."isHidden" ASC,
+  NULLIF("person"."name", '') IS NULL ASC,
+  COUNT("face"."assetId") DESC,
+  NULLIF("person"."name", '') ASC NULLS LAST
+LIMIT
+  500
+
+-- PersonRepository.getAllWithoutFaces
+SELECT
+  "person"."id" AS "person_id",
+  "person"."createdAt" AS "person_createdAt",
+  "person"."updatedAt" AS "person_updatedAt",
+  "person"."ownerId" AS "person_ownerId",
+  "person"."name" AS "person_name",
+  "person"."birthDate" AS "person_birthDate",
+  "person"."thumbnailPath" AS "person_thumbnailPath",
+  "person"."faceAssetId" AS "person_faceAssetId",
+  "person"."isHidden" AS "person_isHidden"
+FROM
+  "person" "person"
+  LEFT JOIN "asset_faces" "face" ON "face"."personId" = "person"."id"
+GROUP BY
+  "person"."id"
+HAVING
+  COUNT("face"."assetId") = 0
+
+-- PersonRepository.getById
+SELECT
+  "PersonEntity"."id" AS "PersonEntity_id",
+  "PersonEntity"."createdAt" AS "PersonEntity_createdAt",
+  "PersonEntity"."updatedAt" AS "PersonEntity_updatedAt",
+  "PersonEntity"."ownerId" AS "PersonEntity_ownerId",
+  "PersonEntity"."name" AS "PersonEntity_name",
+  "PersonEntity"."birthDate" AS "PersonEntity_birthDate",
+  "PersonEntity"."thumbnailPath" AS "PersonEntity_thumbnailPath",
+  "PersonEntity"."faceAssetId" AS "PersonEntity_faceAssetId",
+  "PersonEntity"."isHidden" AS "PersonEntity_isHidden"
+FROM
+  "person" "PersonEntity"
+WHERE
+  ("PersonEntity"."id" = $1)
+LIMIT
+  1
+
+-- PersonRepository.getByName
+SELECT
+  "person"."id" AS "person_id",
+  "person"."createdAt" AS "person_createdAt",
+  "person"."updatedAt" AS "person_updatedAt",
+  "person"."ownerId" AS "person_ownerId",
+  "person"."name" AS "person_name",
+  "person"."birthDate" AS "person_birthDate",
+  "person"."thumbnailPath" AS "person_thumbnailPath",
+  "person"."faceAssetId" AS "person_faceAssetId",
+  "person"."isHidden" AS "person_isHidden"
+FROM
+  "person" "person"
+  LEFT JOIN "asset_faces" "face" ON "face"."personId" = "person"."id"
+WHERE
+  "person"."ownerId" = $1
+  AND (
+    LOWER("person"."name") LIKE $2
+    OR LOWER("person"."name") LIKE $3
+  )
+GROUP BY
+  "person"."id"
+ORDER BY
+  COUNT("face"."assetId") DESC
+LIMIT
+  20
+
+-- PersonRepository.getStatistics
+SELECT DISTINCT
+  COUNT(DISTINCT ("face"."id")) AS "cnt"
+FROM
+  "asset_faces" "face"
+  LEFT JOIN "assets" "asset" ON "asset"."id" = "face"."assetId"
+  AND ("asset"."deletedAt" IS NULL)
+WHERE
+  "face"."personId" = $1
+  AND "asset"."isArchived" = false
+  AND "asset"."deletedAt" IS NULL
+  AND "asset"."livePhotoVideoId" IS NULL
+
+-- PersonRepository.getAssets
+SELECT DISTINCT
+  "distinctAlias"."AssetEntity_id" AS "ids_AssetEntity_id",
+  "distinctAlias"."AssetEntity_fileCreatedAt"
+FROM
+  (
+    SELECT
+      "AssetEntity"."id" AS "AssetEntity_id",
+      "AssetEntity"."deviceAssetId" AS "AssetEntity_deviceAssetId",
+      "AssetEntity"."ownerId" AS "AssetEntity_ownerId",
+      "AssetEntity"."libraryId" AS "AssetEntity_libraryId",
+      "AssetEntity"."deviceId" AS "AssetEntity_deviceId",
+      "AssetEntity"."type" AS "AssetEntity_type",
+      "AssetEntity"."originalPath" AS "AssetEntity_originalPath",
+      "AssetEntity"."resizePath" AS "AssetEntity_resizePath",
+      "AssetEntity"."webpPath" AS "AssetEntity_webpPath",
+      "AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
+      "AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
+      "AssetEntity"."createdAt" AS "AssetEntity_createdAt",
+      "AssetEntity"."updatedAt" AS "AssetEntity_updatedAt",
+      "AssetEntity"."deletedAt" AS "AssetEntity_deletedAt",
+      "AssetEntity"."fileCreatedAt" AS "AssetEntity_fileCreatedAt",
+      "AssetEntity"."localDateTime" AS "AssetEntity_localDateTime",
+      "AssetEntity"."fileModifiedAt" AS "AssetEntity_fileModifiedAt",
+      "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite",
+      "AssetEntity"."isArchived" AS "AssetEntity_isArchived",
+      "AssetEntity"."isExternal" AS "AssetEntity_isExternal",
+      "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly",
+      "AssetEntity"."isOffline" AS "AssetEntity_isOffline",
+      "AssetEntity"."checksum" AS "AssetEntity_checksum",
+      "AssetEntity"."duration" AS "AssetEntity_duration",
+      "AssetEntity"."isVisible" AS "AssetEntity_isVisible",
+      "AssetEntity"."livePhotoVideoId" AS "AssetEntity_livePhotoVideoId",
+      "AssetEntity"."originalFileName" AS "AssetEntity_originalFileName",
+      "AssetEntity"."sidecarPath" AS "AssetEntity_sidecarPath",
+      "AssetEntity"."stackParentId" AS "AssetEntity_stackParentId",
+      "AssetEntity__AssetEntity_faces"."id" AS "AssetEntity__AssetEntity_faces_id",
+      "AssetEntity__AssetEntity_faces"."assetId" AS "AssetEntity__AssetEntity_faces_assetId",
+      "AssetEntity__AssetEntity_faces"."personId" AS "AssetEntity__AssetEntity_faces_personId",
+      "AssetEntity__AssetEntity_faces"."embedding" AS "AssetEntity__AssetEntity_faces_embedding",
+      "AssetEntity__AssetEntity_faces"."imageWidth" AS "AssetEntity__AssetEntity_faces_imageWidth",
+      "AssetEntity__AssetEntity_faces"."imageHeight" AS "AssetEntity__AssetEntity_faces_imageHeight",
+      "AssetEntity__AssetEntity_faces"."boundingBoxX1" AS "AssetEntity__AssetEntity_faces_boundingBoxX1",
+      "AssetEntity__AssetEntity_faces"."boundingBoxY1" AS "AssetEntity__AssetEntity_faces_boundingBoxY1",
+      "AssetEntity__AssetEntity_faces"."boundingBoxX2" AS "AssetEntity__AssetEntity_faces_boundingBoxX2",
+      "AssetEntity__AssetEntity_faces"."boundingBoxY2" AS "AssetEntity__AssetEntity_faces_boundingBoxY2",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_id",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."createdAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_createdAt",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."updatedAt" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_updatedAt",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."ownerId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_ownerId",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."name" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_name",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."birthDate" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_birthDate",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."thumbnailPath" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_thumbnailPath",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."faceAssetId" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_faceAssetId",
+      "8258e303a73a72cf6abb13d73fb592dde0d68280"."isHidden" AS "8258e303a73a72cf6abb13d73fb592dde0d68280_isHidden",
+      "AssetEntity__AssetEntity_exifInfo"."assetId" AS "AssetEntity__AssetEntity_exifInfo_assetId",
+      "AssetEntity__AssetEntity_exifInfo"."description" AS "AssetEntity__AssetEntity_exifInfo_description",
+      "AssetEntity__AssetEntity_exifInfo"."exifImageWidth" AS "AssetEntity__AssetEntity_exifInfo_exifImageWidth",
+      "AssetEntity__AssetEntity_exifInfo"."exifImageHeight" AS "AssetEntity__AssetEntity_exifInfo_exifImageHeight",
+      "AssetEntity__AssetEntity_exifInfo"."fileSizeInByte" AS "AssetEntity__AssetEntity_exifInfo_fileSizeInByte",
+      "AssetEntity__AssetEntity_exifInfo"."orientation" AS "AssetEntity__AssetEntity_exifInfo_orientation",
+      "AssetEntity__AssetEntity_exifInfo"."dateTimeOriginal" AS "AssetEntity__AssetEntity_exifInfo_dateTimeOriginal",
+      "AssetEntity__AssetEntity_exifInfo"."modifyDate" AS "AssetEntity__AssetEntity_exifInfo_modifyDate",
+      "AssetEntity__AssetEntity_exifInfo"."timeZone" AS "AssetEntity__AssetEntity_exifInfo_timeZone",
+      "AssetEntity__AssetEntity_exifInfo"."latitude" AS "AssetEntity__AssetEntity_exifInfo_latitude",
+      "AssetEntity__AssetEntity_exifInfo"."longitude" AS "AssetEntity__AssetEntity_exifInfo_longitude",
+      "AssetEntity__AssetEntity_exifInfo"."projectionType" AS "AssetEntity__AssetEntity_exifInfo_projectionType",
+      "AssetEntity__AssetEntity_exifInfo"."city" AS "AssetEntity__AssetEntity_exifInfo_city",
+      "AssetEntity__AssetEntity_exifInfo"."livePhotoCID" AS "AssetEntity__AssetEntity_exifInfo_livePhotoCID",
+      "AssetEntity__AssetEntity_exifInfo"."state" AS "AssetEntity__AssetEntity_exifInfo_state",
+      "AssetEntity__AssetEntity_exifInfo"."country" AS "AssetEntity__AssetEntity_exifInfo_country",
+      "AssetEntity__AssetEntity_exifInfo"."make" AS "AssetEntity__AssetEntity_exifInfo_make",
+      "AssetEntity__AssetEntity_exifInfo"."model" AS "AssetEntity__AssetEntity_exifInfo_model",
+      "AssetEntity__AssetEntity_exifInfo"."lensModel" AS "AssetEntity__AssetEntity_exifInfo_lensModel",
+      "AssetEntity__AssetEntity_exifInfo"."fNumber" AS "AssetEntity__AssetEntity_exifInfo_fNumber",
+      "AssetEntity__AssetEntity_exifInfo"."focalLength" AS "AssetEntity__AssetEntity_exifInfo_focalLength",
+      "AssetEntity__AssetEntity_exifInfo"."iso" AS "AssetEntity__AssetEntity_exifInfo_iso",
+      "AssetEntity__AssetEntity_exifInfo"."exposureTime" AS "AssetEntity__AssetEntity_exifInfo_exposureTime",
+      "AssetEntity__AssetEntity_exifInfo"."profileDescription" AS "AssetEntity__AssetEntity_exifInfo_profileDescription",
+      "AssetEntity__AssetEntity_exifInfo"."colorspace" AS "AssetEntity__AssetEntity_exifInfo_colorspace",
+      "AssetEntity__AssetEntity_exifInfo"."bitsPerSample" AS "AssetEntity__AssetEntity_exifInfo_bitsPerSample",
+      "AssetEntity__AssetEntity_exifInfo"."fps" AS "AssetEntity__AssetEntity_exifInfo_fps",
+      "AssetEntity__AssetEntity_exifInfo"."exifTextSearchableColumn" AS "AssetEntity__AssetEntity_exifInfo_exifTextSearchableColumn"
+    FROM
+      "assets" "AssetEntity"
+      LEFT JOIN "asset_faces" "AssetEntity__AssetEntity_faces" ON "AssetEntity__AssetEntity_faces"."assetId" = "AssetEntity"."id"
+      LEFT JOIN "person" "8258e303a73a72cf6abb13d73fb592dde0d68280" ON "8258e303a73a72cf6abb13d73fb592dde0d68280"."id" = "AssetEntity__AssetEntity_faces"."personId"
+      LEFT JOIN "exif" "AssetEntity__AssetEntity_exifInfo" ON "AssetEntity__AssetEntity_exifInfo"."assetId" = "AssetEntity"."id"
+    WHERE
+      (
+        (
+          "AssetEntity__AssetEntity_faces"."personId" = $1
+          AND "AssetEntity"."isVisible" = $2
+          AND "AssetEntity"."isArchived" = $3
+        )
+      )
+      AND ("AssetEntity"."deletedAt" IS NULL)
+  ) "distinctAlias"
+ORDER BY
+  "distinctAlias"."AssetEntity_fileCreatedAt" DESC,
+  "AssetEntity_id" ASC
+LIMIT
+  1000
+
+-- PersonRepository.getFacesByIds
+SELECT
+  "AssetFaceEntity"."id" AS "AssetFaceEntity_id",
+  "AssetFaceEntity"."assetId" AS "AssetFaceEntity_assetId",
+  "AssetFaceEntity"."personId" AS "AssetFaceEntity_personId",
+  "AssetFaceEntity"."embedding" AS "AssetFaceEntity_embedding",
+  "AssetFaceEntity"."imageWidth" AS "AssetFaceEntity_imageWidth",
+  "AssetFaceEntity"."imageHeight" AS "AssetFaceEntity_imageHeight",
+  "AssetFaceEntity"."boundingBoxX1" AS "AssetFaceEntity_boundingBoxX1",
+  "AssetFaceEntity"."boundingBoxY1" AS "AssetFaceEntity_boundingBoxY1",
+  "AssetFaceEntity"."boundingBoxX2" AS "AssetFaceEntity_boundingBoxX2",
+  "AssetFaceEntity"."boundingBoxY2" AS "AssetFaceEntity_boundingBoxY2",
+  "AssetFaceEntity__AssetFaceEntity_asset"."id" AS "AssetFaceEntity__AssetFaceEntity_asset_id",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deviceAssetId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceAssetId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."ownerId" AS "AssetFaceEntity__AssetFaceEntity_asset_ownerId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."libraryId" AS "AssetFaceEntity__AssetFaceEntity_asset_libraryId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
+  "AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
+  "AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."updatedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_updatedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."deletedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_deletedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."fileCreatedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_fileCreatedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."localDateTime" AS "AssetFaceEntity__AssetFaceEntity_asset_localDateTime",
+  "AssetFaceEntity__AssetFaceEntity_asset"."fileModifiedAt" AS "AssetFaceEntity__AssetFaceEntity_asset_fileModifiedAt",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isReadOnly" AS "AssetFaceEntity__AssetFaceEntity_asset_isReadOnly",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline",
+  "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum",
+  "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration",
+  "AssetFaceEntity__AssetFaceEntity_asset"."isVisible" AS "AssetFaceEntity__AssetFaceEntity_asset_isVisible",
+  "AssetFaceEntity__AssetFaceEntity_asset"."livePhotoVideoId" AS "AssetFaceEntity__AssetFaceEntity_asset_livePhotoVideoId",
+  "AssetFaceEntity__AssetFaceEntity_asset"."originalFileName" AS "AssetFaceEntity__AssetFaceEntity_asset_originalFileName",
+  "AssetFaceEntity__AssetFaceEntity_asset"."sidecarPath" AS "AssetFaceEntity__AssetFaceEntity_asset_sidecarPath",
+  "AssetFaceEntity__AssetFaceEntity_asset"."stackParentId" AS "AssetFaceEntity__AssetFaceEntity_asset_stackParentId"
+FROM
+  "asset_faces" "AssetFaceEntity"
+  LEFT JOIN "assets" "AssetFaceEntity__AssetFaceEntity_asset" ON "AssetFaceEntity__AssetFaceEntity_asset"."id" = "AssetFaceEntity"."assetId"
+WHERE
+  (
+    (
+      "AssetFaceEntity"."assetId" = $1
+      AND "AssetFaceEntity"."personId" = $2
+    )
+  )
+
+-- PersonRepository.getRandomFace
+SELECT
+  "AssetFaceEntity"."id" AS "AssetFaceEntity_id",
+  "AssetFaceEntity"."assetId" AS "AssetFaceEntity_assetId",
+  "AssetFaceEntity"."personId" AS "AssetFaceEntity_personId",
+  "AssetFaceEntity"."embedding" AS "AssetFaceEntity_embedding",
+  "AssetFaceEntity"."imageWidth" AS "AssetFaceEntity_imageWidth",
+  "AssetFaceEntity"."imageHeight" AS "AssetFaceEntity_imageHeight",
+  "AssetFaceEntity"."boundingBoxX1" AS "AssetFaceEntity_boundingBoxX1",
+  "AssetFaceEntity"."boundingBoxY1" AS "AssetFaceEntity_boundingBoxY1",
+  "AssetFaceEntity"."boundingBoxX2" AS "AssetFaceEntity_boundingBoxX2",
+  "AssetFaceEntity"."boundingBoxY2" AS "AssetFaceEntity_boundingBoxY2"
+FROM
+  "asset_faces" "AssetFaceEntity"
+WHERE
+  ("AssetFaceEntity"."personId" = $1)
+LIMIT
+  1
diff --git a/server/src/infra/sql/shared.link.repository.sql b/server/src/infra/sql/shared.link.repository.sql
new file mode 100644
index 000000000..ffb05cd39
--- /dev/null
+++ b/server/src/infra/sql/shared.link.repository.sql
@@ -0,0 +1,327 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- SharedLinkRepository.get
+SELECT DISTINCT
+  "distinctAlias"."SharedLinkEntity_id" AS "ids_SharedLinkEntity_id",
+  "distinctAlias"."SharedLinkEntity_createdAt",
+  "distinctAlias"."SharedLinkEntity__SharedLinkEntity_assets_fileCreatedAt",
+  "distinctAlias"."4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_fileCreatedAt"
+FROM
+  (
+    SELECT
+      "SharedLinkEntity"."id" AS "SharedLinkEntity_id",
+      "SharedLinkEntity"."description" AS "SharedLinkEntity_description",
+      "SharedLinkEntity"."password" AS "SharedLinkEntity_password",
+      "SharedLinkEntity"."userId" AS "SharedLinkEntity_userId",
+      "SharedLinkEntity"."key" AS "SharedLinkEntity_key",
+      "SharedLinkEntity"."type" AS "SharedLinkEntity_type",
+      "SharedLinkEntity"."createdAt" AS "SharedLinkEntity_createdAt",
+      "SharedLinkEntity"."expiresAt" AS "SharedLinkEntity_expiresAt",
+      "SharedLinkEntity"."allowUpload" AS "SharedLinkEntity_allowUpload",
+      "SharedLinkEntity"."allowDownload" AS "SharedLinkEntity_allowDownload",
+      "SharedLinkEntity"."showExif" AS "SharedLinkEntity_showExif",
+      "SharedLinkEntity"."albumId" AS "SharedLinkEntity_albumId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."id" AS "SharedLinkEntity__SharedLinkEntity_assets_id",
+      "SharedLinkEntity__SharedLinkEntity_assets"."deviceAssetId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceAssetId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."ownerId" AS "SharedLinkEntity__SharedLinkEntity_assets_ownerId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."libraryId" AS "SharedLinkEntity__SharedLinkEntity_assets_libraryId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
+      "SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
+      "SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
+      "SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
+      "SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
+      "SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
+      "SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
+      "SharedLinkEntity__SharedLinkEntity_assets"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_updatedAt",
+      "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_deletedAt",
+      "SharedLinkEntity__SharedLinkEntity_assets"."fileCreatedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_fileCreatedAt",
+      "SharedLinkEntity__SharedLinkEntity_assets"."localDateTime" AS "SharedLinkEntity__SharedLinkEntity_assets_localDateTime",
+      "SharedLinkEntity__SharedLinkEntity_assets"."fileModifiedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_fileModifiedAt",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isReadOnly" AS "SharedLinkEntity__SharedLinkEntity_assets_isReadOnly",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline",
+      "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum",
+      "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration",
+      "SharedLinkEntity__SharedLinkEntity_assets"."isVisible" AS "SharedLinkEntity__SharedLinkEntity_assets_isVisible",
+      "SharedLinkEntity__SharedLinkEntity_assets"."livePhotoVideoId" AS "SharedLinkEntity__SharedLinkEntity_assets_livePhotoVideoId",
+      "SharedLinkEntity__SharedLinkEntity_assets"."originalFileName" AS "SharedLinkEntity__SharedLinkEntity_assets_originalFileName",
+      "SharedLinkEntity__SharedLinkEntity_assets"."sidecarPath" AS "SharedLinkEntity__SharedLinkEntity_assets_sidecarPath",
+      "SharedLinkEntity__SharedLinkEntity_assets"."stackParentId" AS "SharedLinkEntity__SharedLinkEntity_assets_stackParentId",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."assetId" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_assetId",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."description" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_description",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."exifImageWidth" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_exifImageWidth",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."exifImageHeight" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_exifImageHeight",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."fileSizeInByte" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_fileSizeInByte",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."orientation" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_orientation",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."dateTimeOriginal" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_dateTimeOriginal",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."modifyDate" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_modifyDate",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."timeZone" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_timeZone",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."latitude" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_latitude",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."longitude" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_longitude",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."projectionType" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_projectionType",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."city" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_city",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."livePhotoCID" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_livePhotoCID",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."state" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_state",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."country" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_country",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."make" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_make",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."model" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_model",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."lensModel" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_lensModel",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."fNumber" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_fNumber",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."focalLength" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_focalLength",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."iso" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_iso",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."exposureTime" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_exposureTime",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."profileDescription" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_profileDescription",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."colorspace" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_colorspace",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."bitsPerSample" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_bitsPerSample",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."fps" AS "9b1d35b344d838023994a3233afd6ffe098be6d8_fps",
+      "9b1d35b344d838023994a3233afd6ffe098be6d8"."exifTextSearchableColumn" AS "e18de9deffa83f81ac3c43b5e8c2f08dba727bf8",
+      "SharedLinkEntity__SharedLinkEntity_album"."id" AS "SharedLinkEntity__SharedLinkEntity_album_id",
+      "SharedLinkEntity__SharedLinkEntity_album"."ownerId" AS "SharedLinkEntity__SharedLinkEntity_album_ownerId",
+      "SharedLinkEntity__SharedLinkEntity_album"."albumName" AS "SharedLinkEntity__SharedLinkEntity_album_albumName",
+      "SharedLinkEntity__SharedLinkEntity_album"."description" AS "SharedLinkEntity__SharedLinkEntity_album_description",
+      "SharedLinkEntity__SharedLinkEntity_album"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_album_createdAt",
+      "SharedLinkEntity__SharedLinkEntity_album"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_album_updatedAt",
+      "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_album_deletedAt",
+      "SharedLinkEntity__SharedLinkEntity_album"."albumThumbnailAssetId" AS "SharedLinkEntity__SharedLinkEntity_album_albumThumbnailAssetId",
+      "SharedLinkEntity__SharedLinkEntity_album"."isActivityEnabled" AS "SharedLinkEntity__SharedLinkEntity_album_isActivityEnabled",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_id",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deviceAssetId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deviceAssetId",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."ownerId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_ownerId",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."libraryId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_libraryId",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deviceId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deviceId",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."type" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_type",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."originalPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_originalPath",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."resizePath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_resizePath",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."webpPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_webpPath",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbhash" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbhash",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."encodedVideoPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_encodedVideoPath",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."createdAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_createdAt",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."updatedAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_updatedAt",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deletedAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deletedAt",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."fileCreatedAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_fileCreatedAt",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."localDateTime" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_localDateTime",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."fileModifiedAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_fileModifiedAt",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isFavorite" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isFavorite",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isArchived" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isArchived",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isExternal" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isExternal",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isReadOnly" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isReadOnly",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isOffline" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isOffline",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."checksum" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_checksum",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."duration" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_duration",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isVisible" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isVisible",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."livePhotoVideoId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_livePhotoVideoId",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."originalFileName" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_originalFileName",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."sidecarPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_sidecarPath",
+      "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."stackParentId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_stackParentId",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."assetId" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_assetId",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."description" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_description",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."exifImageWidth" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_exifImageWidth",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."exifImageHeight" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_exifImageHeight",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."fileSizeInByte" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_fileSizeInByte",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."orientation" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_orientation",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."dateTimeOriginal" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_dateTimeOriginal",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."modifyDate" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_modifyDate",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."timeZone" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_timeZone",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."latitude" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_latitude",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."longitude" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_longitude",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."projectionType" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_projectionType",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."city" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_city",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."livePhotoCID" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_livePhotoCID",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."state" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_state",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."country" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_country",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."make" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_make",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."model" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_model",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."lensModel" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_lensModel",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."fNumber" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_fNumber",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."focalLength" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_focalLength",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."iso" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_iso",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."exposureTime" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_exposureTime",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."profileDescription" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_profileDescription",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."colorspace" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_colorspace",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."bitsPerSample" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_bitsPerSample",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."fps" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_fps",
+      "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."exifTextSearchableColumn" AS "96535c8046de591cca9b8c5825e6c5db502b0e6a",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_id",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."name" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_name",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."avatarColor" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_avatarColor",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."isAdmin" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_isAdmin",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."email" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_email",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."storageLabel" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_storageLabel",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."externalPath" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_externalPath",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."oauthId" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_oauthId",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."profileImagePath" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_profileImagePath",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."shouldChangePassword" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_shouldChangePassword",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."createdAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_createdAt",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_deletedAt",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."updatedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_updatedAt",
+      "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."memoriesEnabled" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_memoriesEnabled"
+    FROM
+      "shared_links" "SharedLinkEntity"
+      LEFT JOIN "shared_link__asset" "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity" ON "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."sharedLinksId" = "SharedLinkEntity"."id"
+      LEFT JOIN "assets" "SharedLinkEntity__SharedLinkEntity_assets" ON "SharedLinkEntity__SharedLinkEntity_assets"."id" = "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."assetsId"
+      AND (
+        "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" IS NULL
+      )
+      LEFT JOIN "exif" "9b1d35b344d838023994a3233afd6ffe098be6d8" ON "9b1d35b344d838023994a3233afd6ffe098be6d8"."assetId" = "SharedLinkEntity__SharedLinkEntity_assets"."id"
+      LEFT JOIN "albums" "SharedLinkEntity__SharedLinkEntity_album" ON "SharedLinkEntity__SharedLinkEntity_album"."id" = "SharedLinkEntity"."albumId"
+      AND (
+        "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" IS NULL
+      )
+      LEFT JOIN "albums_assets_assets" "760f12c00d97bdcec1ce224d1e3bf449859942b6" ON "760f12c00d97bdcec1ce224d1e3bf449859942b6"."albumsId" = "SharedLinkEntity__SharedLinkEntity_album"."id"
+      LEFT JOIN "assets" "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6" ON "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id" = "760f12c00d97bdcec1ce224d1e3bf449859942b6"."assetsId"
+      AND (
+        "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deletedAt" IS NULL
+      )
+      LEFT JOIN "exif" "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f" ON "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."assetId" = "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id"
+      LEFT JOIN "users" "6d7fd45329a05fd86b3dbcacde87fe76e33a422d" ON "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" = "SharedLinkEntity__SharedLinkEntity_album"."ownerId"
+      AND (
+        "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" IS NULL
+      )
+    WHERE
+      (
+        "SharedLinkEntity"."id" = $1
+        AND "SharedLinkEntity"."userId" = $2
+      )
+  ) "distinctAlias"
+ORDER BY
+  "distinctAlias"."SharedLinkEntity_createdAt" DESC,
+  "distinctAlias"."SharedLinkEntity__SharedLinkEntity_assets_fileCreatedAt" ASC,
+  "distinctAlias"."4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_fileCreatedAt" ASC,
+  "SharedLinkEntity_id" ASC
+LIMIT
+  1
+
+-- SharedLinkRepository.getAll
+SELECT
+  "SharedLinkEntity"."id" AS "SharedLinkEntity_id",
+  "SharedLinkEntity"."description" AS "SharedLinkEntity_description",
+  "SharedLinkEntity"."password" AS "SharedLinkEntity_password",
+  "SharedLinkEntity"."userId" AS "SharedLinkEntity_userId",
+  "SharedLinkEntity"."key" AS "SharedLinkEntity_key",
+  "SharedLinkEntity"."type" AS "SharedLinkEntity_type",
+  "SharedLinkEntity"."createdAt" AS "SharedLinkEntity_createdAt",
+  "SharedLinkEntity"."expiresAt" AS "SharedLinkEntity_expiresAt",
+  "SharedLinkEntity"."allowUpload" AS "SharedLinkEntity_allowUpload",
+  "SharedLinkEntity"."allowDownload" AS "SharedLinkEntity_allowDownload",
+  "SharedLinkEntity"."showExif" AS "SharedLinkEntity_showExif",
+  "SharedLinkEntity"."albumId" AS "SharedLinkEntity_albumId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."id" AS "SharedLinkEntity__SharedLinkEntity_assets_id",
+  "SharedLinkEntity__SharedLinkEntity_assets"."deviceAssetId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceAssetId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."ownerId" AS "SharedLinkEntity__SharedLinkEntity_assets_ownerId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."libraryId" AS "SharedLinkEntity__SharedLinkEntity_assets_libraryId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
+  "SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
+  "SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
+  "SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
+  "SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
+  "SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
+  "SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
+  "SharedLinkEntity__SharedLinkEntity_assets"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_updatedAt",
+  "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_deletedAt",
+  "SharedLinkEntity__SharedLinkEntity_assets"."fileCreatedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_fileCreatedAt",
+  "SharedLinkEntity__SharedLinkEntity_assets"."localDateTime" AS "SharedLinkEntity__SharedLinkEntity_assets_localDateTime",
+  "SharedLinkEntity__SharedLinkEntity_assets"."fileModifiedAt" AS "SharedLinkEntity__SharedLinkEntity_assets_fileModifiedAt",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isReadOnly" AS "SharedLinkEntity__SharedLinkEntity_assets_isReadOnly",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline",
+  "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum",
+  "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration",
+  "SharedLinkEntity__SharedLinkEntity_assets"."isVisible" AS "SharedLinkEntity__SharedLinkEntity_assets_isVisible",
+  "SharedLinkEntity__SharedLinkEntity_assets"."livePhotoVideoId" AS "SharedLinkEntity__SharedLinkEntity_assets_livePhotoVideoId",
+  "SharedLinkEntity__SharedLinkEntity_assets"."originalFileName" AS "SharedLinkEntity__SharedLinkEntity_assets_originalFileName",
+  "SharedLinkEntity__SharedLinkEntity_assets"."sidecarPath" AS "SharedLinkEntity__SharedLinkEntity_assets_sidecarPath",
+  "SharedLinkEntity__SharedLinkEntity_assets"."stackParentId" AS "SharedLinkEntity__SharedLinkEntity_assets_stackParentId",
+  "SharedLinkEntity__SharedLinkEntity_album"."id" AS "SharedLinkEntity__SharedLinkEntity_album_id",
+  "SharedLinkEntity__SharedLinkEntity_album"."ownerId" AS "SharedLinkEntity__SharedLinkEntity_album_ownerId",
+  "SharedLinkEntity__SharedLinkEntity_album"."albumName" AS "SharedLinkEntity__SharedLinkEntity_album_albumName",
+  "SharedLinkEntity__SharedLinkEntity_album"."description" AS "SharedLinkEntity__SharedLinkEntity_album_description",
+  "SharedLinkEntity__SharedLinkEntity_album"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_album_createdAt",
+  "SharedLinkEntity__SharedLinkEntity_album"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_album_updatedAt",
+  "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_album_deletedAt",
+  "SharedLinkEntity__SharedLinkEntity_album"."albumThumbnailAssetId" AS "SharedLinkEntity__SharedLinkEntity_album_albumThumbnailAssetId",
+  "SharedLinkEntity__SharedLinkEntity_album"."isActivityEnabled" AS "SharedLinkEntity__SharedLinkEntity_album_isActivityEnabled",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_id",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."name" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_name",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."avatarColor" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_avatarColor",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."isAdmin" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_isAdmin",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."email" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_email",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."storageLabel" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_storageLabel",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."externalPath" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_externalPath",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."oauthId" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_oauthId",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."profileImagePath" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_profileImagePath",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."shouldChangePassword" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_shouldChangePassword",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."createdAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_createdAt",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_deletedAt",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."updatedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_updatedAt",
+  "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."memoriesEnabled" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_memoriesEnabled"
+FROM
+  "shared_links" "SharedLinkEntity"
+  LEFT JOIN "shared_link__asset" "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity" ON "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."sharedLinksId" = "SharedLinkEntity"."id"
+  LEFT JOIN "assets" "SharedLinkEntity__SharedLinkEntity_assets" ON "SharedLinkEntity__SharedLinkEntity_assets"."id" = "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."assetsId"
+  AND (
+    "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" IS NULL
+  )
+  LEFT JOIN "albums" "SharedLinkEntity__SharedLinkEntity_album" ON "SharedLinkEntity__SharedLinkEntity_album"."id" = "SharedLinkEntity"."albumId"
+  AND (
+    "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" IS NULL
+  )
+  LEFT JOIN "users" "6d7fd45329a05fd86b3dbcacde87fe76e33a422d" ON "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" = "SharedLinkEntity__SharedLinkEntity_album"."ownerId"
+  AND (
+    "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" IS NULL
+  )
+WHERE
+  ("SharedLinkEntity"."userId" = $1)
+ORDER BY
+  "SharedLinkEntity"."createdAt" DESC
+
+-- SharedLinkRepository.getByKey
+SELECT DISTINCT
+  "distinctAlias"."SharedLinkEntity_id" AS "ids_SharedLinkEntity_id"
+FROM
+  (
+    SELECT
+      "SharedLinkEntity"."id" AS "SharedLinkEntity_id",
+      "SharedLinkEntity"."description" AS "SharedLinkEntity_description",
+      "SharedLinkEntity"."password" AS "SharedLinkEntity_password",
+      "SharedLinkEntity"."userId" AS "SharedLinkEntity_userId",
+      "SharedLinkEntity"."key" AS "SharedLinkEntity_key",
+      "SharedLinkEntity"."type" AS "SharedLinkEntity_type",
+      "SharedLinkEntity"."createdAt" AS "SharedLinkEntity_createdAt",
+      "SharedLinkEntity"."expiresAt" AS "SharedLinkEntity_expiresAt",
+      "SharedLinkEntity"."allowUpload" AS "SharedLinkEntity_allowUpload",
+      "SharedLinkEntity"."allowDownload" AS "SharedLinkEntity_allowDownload",
+      "SharedLinkEntity"."showExif" AS "SharedLinkEntity_showExif",
+      "SharedLinkEntity"."albumId" AS "SharedLinkEntity_albumId",
+      "SharedLinkEntity__SharedLinkEntity_user"."id" AS "SharedLinkEntity__SharedLinkEntity_user_id",
+      "SharedLinkEntity__SharedLinkEntity_user"."name" AS "SharedLinkEntity__SharedLinkEntity_user_name",
+      "SharedLinkEntity__SharedLinkEntity_user"."avatarColor" AS "SharedLinkEntity__SharedLinkEntity_user_avatarColor",
+      "SharedLinkEntity__SharedLinkEntity_user"."isAdmin" AS "SharedLinkEntity__SharedLinkEntity_user_isAdmin",
+      "SharedLinkEntity__SharedLinkEntity_user"."email" AS "SharedLinkEntity__SharedLinkEntity_user_email",
+      "SharedLinkEntity__SharedLinkEntity_user"."storageLabel" AS "SharedLinkEntity__SharedLinkEntity_user_storageLabel",
+      "SharedLinkEntity__SharedLinkEntity_user"."externalPath" AS "SharedLinkEntity__SharedLinkEntity_user_externalPath",
+      "SharedLinkEntity__SharedLinkEntity_user"."oauthId" AS "SharedLinkEntity__SharedLinkEntity_user_oauthId",
+      "SharedLinkEntity__SharedLinkEntity_user"."profileImagePath" AS "SharedLinkEntity__SharedLinkEntity_user_profileImagePath",
+      "SharedLinkEntity__SharedLinkEntity_user"."shouldChangePassword" AS "SharedLinkEntity__SharedLinkEntity_user_shouldChangePassword",
+      "SharedLinkEntity__SharedLinkEntity_user"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_user_createdAt",
+      "SharedLinkEntity__SharedLinkEntity_user"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_user_deletedAt",
+      "SharedLinkEntity__SharedLinkEntity_user"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_user_updatedAt",
+      "SharedLinkEntity__SharedLinkEntity_user"."memoriesEnabled" AS "SharedLinkEntity__SharedLinkEntity_user_memoriesEnabled"
+    FROM
+      "shared_links" "SharedLinkEntity"
+      LEFT JOIN "users" "SharedLinkEntity__SharedLinkEntity_user" ON "SharedLinkEntity__SharedLinkEntity_user"."id" = "SharedLinkEntity"."userId"
+      AND (
+        "SharedLinkEntity__SharedLinkEntity_user"."deletedAt" IS NULL
+      )
+    WHERE
+      ("SharedLinkEntity"."key" = $1)
+  ) "distinctAlias"
+ORDER BY
+  "SharedLinkEntity_id" ASC
+LIMIT
+  1
diff --git a/server/src/infra/sql/system.config.repository.sql b/server/src/infra/sql/system.config.repository.sql
new file mode 100644
index 000000000..276cab20f
--- /dev/null
+++ b/server/src/infra/sql/system.config.repository.sql
@@ -0,0 +1,13 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- SystemConfigRepository.load
+SELECT
+  "SystemConfigEntity"."key" AS "SystemConfigEntity_key",
+  "SystemConfigEntity"."value" AS "SystemConfigEntity_value"
+FROM
+  "system_config" "SystemConfigEntity"
+
+-- SystemConfigRepository.deleteKeys
+DELETE FROM "system_config"
+WHERE
+  "key" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9)
diff --git a/server/src/infra/sql/system.metadata.repository.sql b/server/src/infra/sql/system.metadata.repository.sql
new file mode 100644
index 000000000..21f9f116b
--- /dev/null
+++ b/server/src/infra/sql/system.metadata.repository.sql
@@ -0,0 +1 @@
+-- NOTE: This file is auto generated by ./sql-generator
diff --git a/server/src/infra/sql/tag.repository.sql b/server/src/infra/sql/tag.repository.sql
new file mode 100644
index 000000000..21f9f116b
--- /dev/null
+++ b/server/src/infra/sql/tag.repository.sql
@@ -0,0 +1 @@
+-- NOTE: This file is auto generated by ./sql-generator
diff --git a/server/src/infra/sql/user.repository.sql b/server/src/infra/sql/user.repository.sql
new file mode 100644
index 000000000..d21f1e7b0
--- /dev/null
+++ b/server/src/infra/sql/user.repository.sql
@@ -0,0 +1,143 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- UserRepository.getAdmin
+SELECT
+  "UserEntity"."id" AS "UserEntity_id",
+  "UserEntity"."name" AS "UserEntity_name",
+  "UserEntity"."avatarColor" AS "UserEntity_avatarColor",
+  "UserEntity"."isAdmin" AS "UserEntity_isAdmin",
+  "UserEntity"."email" AS "UserEntity_email",
+  "UserEntity"."storageLabel" AS "UserEntity_storageLabel",
+  "UserEntity"."externalPath" AS "UserEntity_externalPath",
+  "UserEntity"."oauthId" AS "UserEntity_oauthId",
+  "UserEntity"."profileImagePath" AS "UserEntity_profileImagePath",
+  "UserEntity"."shouldChangePassword" AS "UserEntity_shouldChangePassword",
+  "UserEntity"."createdAt" AS "UserEntity_createdAt",
+  "UserEntity"."deletedAt" AS "UserEntity_deletedAt",
+  "UserEntity"."updatedAt" AS "UserEntity_updatedAt",
+  "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled"
+FROM
+  "users" "UserEntity"
+WHERE
+  (("UserEntity"."isAdmin" = $1))
+  AND ("UserEntity"."deletedAt" IS NULL)
+LIMIT
+  1
+
+-- UserRepository.hasAdmin
+SELECT
+  1 AS "row_exists"
+FROM
+  (
+    SELECT
+      1 AS dummy_column
+  ) "dummy_table"
+WHERE
+  EXISTS (
+    SELECT
+      1
+    FROM
+      "users" "UserEntity"
+    WHERE
+      (("UserEntity"."isAdmin" = $1))
+      AND ("UserEntity"."deletedAt" IS NULL)
+  )
+LIMIT
+  1
+
+-- UserRepository.getByEmail
+SELECT
+  "user"."id" AS "user_id",
+  "user"."name" AS "user_name",
+  "user"."avatarColor" AS "user_avatarColor",
+  "user"."isAdmin" AS "user_isAdmin",
+  "user"."email" AS "user_email",
+  "user"."storageLabel" AS "user_storageLabel",
+  "user"."externalPath" AS "user_externalPath",
+  "user"."oauthId" AS "user_oauthId",
+  "user"."profileImagePath" AS "user_profileImagePath",
+  "user"."shouldChangePassword" AS "user_shouldChangePassword",
+  "user"."createdAt" AS "user_createdAt",
+  "user"."deletedAt" AS "user_deletedAt",
+  "user"."updatedAt" AS "user_updatedAt",
+  "user"."memoriesEnabled" AS "user_memoriesEnabled"
+FROM
+  "users" "user"
+WHERE
+  ("user"."email" = $1)
+  AND ("user"."deletedAt" IS NULL)
+
+-- UserRepository.getByStorageLabel
+SELECT
+  "UserEntity"."id" AS "UserEntity_id",
+  "UserEntity"."name" AS "UserEntity_name",
+  "UserEntity"."avatarColor" AS "UserEntity_avatarColor",
+  "UserEntity"."isAdmin" AS "UserEntity_isAdmin",
+  "UserEntity"."email" AS "UserEntity_email",
+  "UserEntity"."storageLabel" AS "UserEntity_storageLabel",
+  "UserEntity"."externalPath" AS "UserEntity_externalPath",
+  "UserEntity"."oauthId" AS "UserEntity_oauthId",
+  "UserEntity"."profileImagePath" AS "UserEntity_profileImagePath",
+  "UserEntity"."shouldChangePassword" AS "UserEntity_shouldChangePassword",
+  "UserEntity"."createdAt" AS "UserEntity_createdAt",
+  "UserEntity"."deletedAt" AS "UserEntity_deletedAt",
+  "UserEntity"."updatedAt" AS "UserEntity_updatedAt",
+  "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled"
+FROM
+  "users" "UserEntity"
+WHERE
+  (("UserEntity"."storageLabel" = $1))
+  AND ("UserEntity"."deletedAt" IS NULL)
+LIMIT
+  1
+
+-- UserRepository.getByOAuthId
+SELECT
+  "UserEntity"."id" AS "UserEntity_id",
+  "UserEntity"."name" AS "UserEntity_name",
+  "UserEntity"."avatarColor" AS "UserEntity_avatarColor",
+  "UserEntity"."isAdmin" AS "UserEntity_isAdmin",
+  "UserEntity"."email" AS "UserEntity_email",
+  "UserEntity"."storageLabel" AS "UserEntity_storageLabel",
+  "UserEntity"."externalPath" AS "UserEntity_externalPath",
+  "UserEntity"."oauthId" AS "UserEntity_oauthId",
+  "UserEntity"."profileImagePath" AS "UserEntity_profileImagePath",
+  "UserEntity"."shouldChangePassword" AS "UserEntity_shouldChangePassword",
+  "UserEntity"."createdAt" AS "UserEntity_createdAt",
+  "UserEntity"."deletedAt" AS "UserEntity_deletedAt",
+  "UserEntity"."updatedAt" AS "UserEntity_updatedAt",
+  "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled"
+FROM
+  "users" "UserEntity"
+WHERE
+  (("UserEntity"."oauthId" = $1))
+  AND ("UserEntity"."deletedAt" IS NULL)
+LIMIT
+  1
+
+-- UserRepository.getUserStats
+SELECT
+  "users"."id" AS "userId",
+  "users"."name" AS "userName",
+  COUNT("assets"."id") FILTER (
+    WHERE
+      "assets"."type" = 'IMAGE'
+      AND "assets"."isVisible"
+  ) AS "photos",
+  COUNT("assets"."id") FILTER (
+    WHERE
+      "assets"."type" = 'VIDEO'
+      AND "assets"."isVisible"
+  ) AS "videos",
+  COALESCE(SUM("exif"."fileSizeInByte"), 0) AS "usage"
+FROM
+  "users" "users"
+  LEFT JOIN "assets" "assets" ON "assets"."ownerId" = "users"."id"
+  AND ("assets"."deletedAt" IS NULL)
+  LEFT JOIN "exif" "exif" ON "exif"."assetId" = "assets"."id"
+WHERE
+  "users"."deletedAt" IS NULL
+GROUP BY
+  "users"."id"
+ORDER BY
+  "users"."createdAt" ASC
diff --git a/server/src/infra/sql/user.token.repository.sql b/server/src/infra/sql/user.token.repository.sql
new file mode 100644
index 000000000..e1d190622
--- /dev/null
+++ b/server/src/infra/sql/user.token.repository.sql
@@ -0,0 +1,46 @@
+-- NOTE: This file is auto generated by ./sql-generator
+
+-- UserTokenRepository.getByToken
+SELECT DISTINCT
+  "distinctAlias"."UserTokenEntity_id" AS "ids_UserTokenEntity_id"
+FROM
+  (
+    SELECT
+      "UserTokenEntity"."id" AS "UserTokenEntity_id",
+      "UserTokenEntity"."userId" AS "UserTokenEntity_userId",
+      "UserTokenEntity"."createdAt" AS "UserTokenEntity_createdAt",
+      "UserTokenEntity"."updatedAt" AS "UserTokenEntity_updatedAt",
+      "UserTokenEntity"."deviceType" AS "UserTokenEntity_deviceType",
+      "UserTokenEntity"."deviceOS" AS "UserTokenEntity_deviceOS",
+      "UserTokenEntity__UserTokenEntity_user"."id" AS "UserTokenEntity__UserTokenEntity_user_id",
+      "UserTokenEntity__UserTokenEntity_user"."name" AS "UserTokenEntity__UserTokenEntity_user_name",
+      "UserTokenEntity__UserTokenEntity_user"."avatarColor" AS "UserTokenEntity__UserTokenEntity_user_avatarColor",
+      "UserTokenEntity__UserTokenEntity_user"."isAdmin" AS "UserTokenEntity__UserTokenEntity_user_isAdmin",
+      "UserTokenEntity__UserTokenEntity_user"."email" AS "UserTokenEntity__UserTokenEntity_user_email",
+      "UserTokenEntity__UserTokenEntity_user"."storageLabel" AS "UserTokenEntity__UserTokenEntity_user_storageLabel",
+      "UserTokenEntity__UserTokenEntity_user"."externalPath" AS "UserTokenEntity__UserTokenEntity_user_externalPath",
+      "UserTokenEntity__UserTokenEntity_user"."oauthId" AS "UserTokenEntity__UserTokenEntity_user_oauthId",
+      "UserTokenEntity__UserTokenEntity_user"."profileImagePath" AS "UserTokenEntity__UserTokenEntity_user_profileImagePath",
+      "UserTokenEntity__UserTokenEntity_user"."shouldChangePassword" AS "UserTokenEntity__UserTokenEntity_user_shouldChangePassword",
+      "UserTokenEntity__UserTokenEntity_user"."createdAt" AS "UserTokenEntity__UserTokenEntity_user_createdAt",
+      "UserTokenEntity__UserTokenEntity_user"."deletedAt" AS "UserTokenEntity__UserTokenEntity_user_deletedAt",
+      "UserTokenEntity__UserTokenEntity_user"."updatedAt" AS "UserTokenEntity__UserTokenEntity_user_updatedAt",
+      "UserTokenEntity__UserTokenEntity_user"."memoriesEnabled" AS "UserTokenEntity__UserTokenEntity_user_memoriesEnabled"
+    FROM
+      "user_token" "UserTokenEntity"
+      LEFT JOIN "users" "UserTokenEntity__UserTokenEntity_user" ON "UserTokenEntity__UserTokenEntity_user"."id" = "UserTokenEntity"."userId"
+      AND (
+        "UserTokenEntity__UserTokenEntity_user"."deletedAt" IS NULL
+      )
+    WHERE
+      ("UserTokenEntity"."token" = $1)
+  ) "distinctAlias"
+ORDER BY
+  "UserTokenEntity_id" ASC
+LIMIT
+  1
+
+-- UserTokenRepository.delete
+DELETE FROM "user_token"
+WHERE
+  "id" = $1