diff --git a/web/prisma/migrations/20260711145610_library_item_optional_request/migration.sql b/web/prisma/migrations/20260711145610_library_item_optional_request/migration.sql new file mode 100644 index 0000000..e9a28f9 --- /dev/null +++ b/web/prisma/migrations/20260711145610_library_item_optional_request/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "LibraryItem" ALTER COLUMN "requestId" DROP NOT NULL; diff --git a/web/prisma/schema.prisma b/web/prisma/schema.prisma index 6eac875..ebac747 100644 --- a/web/prisma/schema.prisma +++ b/web/prisma/schema.prisma @@ -72,8 +72,8 @@ model Candidate { model LibraryItem { id String @id @default(cuid()) - request Request @relation(fields: [requestId], references: [id], onDelete: Cascade) - requestId String @unique + request Request? @relation(fields: [requestId], references: [id], onDelete: Cascade) + requestId String? @unique artist String album String path String diff --git a/web/src/test/setup.ts b/web/src/test/setup.ts index d4bb9b1..7677b47 100644 --- a/web/src/test/setup.ts +++ b/web/src/test/setup.ts @@ -12,6 +12,7 @@ beforeEach(async () => { // Job cascades from Request; Request.monitoredReleaseId is SetNull. Delete children first. await prisma.job.deleteMany(); await prisma.request.deleteMany(); + await prisma.libraryItem.deleteMany(); await prisma.monitoredRelease.deleteMany(); await prisma.watchedArtist.deleteMany(); await prisma.config.deleteMany(); diff --git a/worker/tests/conftest.py b/worker/tests/conftest.py index db298f3..d428b3b 100644 --- a/worker/tests/conftest.py +++ b/worker/tests/conftest.py @@ -24,6 +24,7 @@ def conn(): with connection.cursor() as cur: cur.execute('DELETE FROM "Job"') cur.execute('DELETE FROM "Request"') + cur.execute('DELETE FROM "LibraryItem"') cur.execute('DELETE FROM "MonitoredRelease"') cur.execute('DELETE FROM "WatchedArtist"') cur.execute('DELETE FROM "Config"') @@ -33,6 +34,7 @@ def conn(): with connection.cursor() as cur: cur.execute('DELETE FROM "Job"') cur.execute('DELETE FROM "Request"') + cur.execute('DELETE FROM "LibraryItem"') cur.execute('DELETE FROM "MonitoredRelease"') cur.execute('DELETE FROM "WatchedArtist"') cur.execute('DELETE FROM "Config"') diff --git a/worker/tests/test_library_item_optional_request.py b/worker/tests/test_library_item_optional_request.py new file mode 100644 index 0000000..c60b5c5 --- /dev/null +++ b/worker/tests/test_library_item_optional_request.py @@ -0,0 +1,13 @@ +def test_library_item_can_have_null_request(conn): + with conn.cursor() as cur: + cur.execute( + 'INSERT INTO "LibraryItem" (id, "requestId", artist, album, path, source, format, ' + '"qualityClass", "importedAt") ' + "VALUES (gen_random_uuid()::text, NULL, 'A', 'B', '/m/A/B', 'scan', 'FLAC', 2, now()) " + "RETURNING id" + ) + lib_id = cur.fetchone()[0] + conn.commit() + with conn.cursor() as cur: + cur.execute('SELECT "requestId" FROM "LibraryItem" WHERE id = %s', (lib_id,)) + assert cur.fetchone()[0] is None