db: remove table suffix from schemas
This commit is contained in:
@@ -1,11 +1,5 @@
|
||||
import { desc, eq, like } from "drizzle-orm";
|
||||
import {
|
||||
animeSongLinksTable,
|
||||
animeTable,
|
||||
artistsTable,
|
||||
groupsTable,
|
||||
songsTable,
|
||||
} from "$lib/db/schema";
|
||||
import { anime, animeSongLinks, artists, groups, songs } from "$lib/db/schema";
|
||||
import type { ClientDb } from "./index";
|
||||
|
||||
/**
|
||||
@@ -31,18 +25,14 @@ export async function getAnimeList(db: ClientDb, limit = DEFAULT_LIST_LIMIT) {
|
||||
// Explicit selection keeps payload small and gives a stable, inferred return type
|
||||
return db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
year: animeTable.year,
|
||||
seasonId: animeTable.seasonId,
|
||||
malId: animeTable.malId,
|
||||
annId: anime.annId,
|
||||
mainName: anime.mainName,
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
})
|
||||
.from(animeTable)
|
||||
.orderBy(
|
||||
desc(animeTable.year),
|
||||
desc(animeTable.seasonId),
|
||||
desc(animeTable.annId),
|
||||
)
|
||||
.from(anime)
|
||||
.orderBy(desc(anime.year), desc(anime.seasonId), desc(anime.annId))
|
||||
.limit(safeLimit);
|
||||
}
|
||||
|
||||
@@ -65,19 +55,15 @@ export async function searchAnimeByName(
|
||||
|
||||
return db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
year: animeTable.year,
|
||||
seasonId: animeTable.seasonId,
|
||||
malId: animeTable.malId,
|
||||
annId: anime.annId,
|
||||
mainName: anime.mainName,
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
})
|
||||
.from(animeTable)
|
||||
.where(like(animeTable.mainName, pattern))
|
||||
.orderBy(
|
||||
desc(animeTable.year),
|
||||
desc(animeTable.seasonId),
|
||||
desc(animeTable.annId),
|
||||
)
|
||||
.from(anime)
|
||||
.where(like(anime.mainName, pattern))
|
||||
.orderBy(desc(anime.year), desc(anime.seasonId), desc(anime.annId))
|
||||
.limit(safeLimit);
|
||||
}
|
||||
|
||||
@@ -93,43 +79,37 @@ export async function searchAnimeByName(
|
||||
export async function getAnimeWithSongsByAnnId(db: ClientDb, annId: number) {
|
||||
const animeRows = await db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
year: animeTable.year,
|
||||
seasonId: animeTable.seasonId,
|
||||
malId: animeTable.malId,
|
||||
annId: anime.annId,
|
||||
mainName: anime.mainName,
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
})
|
||||
.from(animeTable)
|
||||
.where(eq(animeTable.annId, annId))
|
||||
.from(anime)
|
||||
.where(eq(anime.annId, annId))
|
||||
.limit(1);
|
||||
|
||||
const anime = animeRows[0];
|
||||
if (!anime) return null;
|
||||
const foundAnime = animeRows[0];
|
||||
if (!foundAnime) return null;
|
||||
|
||||
const rows = await db
|
||||
.select({
|
||||
annSongId: animeSongLinksTable.annSongId,
|
||||
type: animeSongLinksTable.type,
|
||||
number: animeSongLinksTable.number,
|
||||
annSongId: animeSongLinks.annSongId,
|
||||
type: animeSongLinks.type,
|
||||
number: animeSongLinks.number,
|
||||
|
||||
songName: songsTable.name,
|
||||
fileName: songsTable.fileName,
|
||||
songName: songs.name,
|
||||
fileName: songs.fileName,
|
||||
|
||||
artistName: artistsTable.name,
|
||||
groupName: groupsTable.name,
|
||||
artistName: artists.name,
|
||||
groupName: groups.name,
|
||||
})
|
||||
.from(animeSongLinksTable)
|
||||
.innerJoin(
|
||||
songsTable,
|
||||
eq(songsTable.annSongId, animeSongLinksTable.annSongId),
|
||||
)
|
||||
.leftJoin(
|
||||
artistsTable,
|
||||
eq(artistsTable.songArtistId, songsTable.songArtistId),
|
||||
)
|
||||
.leftJoin(groupsTable, eq(groupsTable.songGroupId, songsTable.songGroupId))
|
||||
.where(eq(animeSongLinksTable.annId, annId))
|
||||
.orderBy(desc(animeSongLinksTable.type), desc(animeSongLinksTable.number));
|
||||
.from(animeSongLinks)
|
||||
.innerJoin(songs, eq(songs.annSongId, animeSongLinks.annSongId))
|
||||
.leftJoin(artists, eq(artists.songArtistId, songs.songArtistId))
|
||||
.leftJoin(groups, eq(groups.songGroupId, songs.songGroupId))
|
||||
.where(eq(animeSongLinks.annId, annId))
|
||||
.orderBy(desc(animeSongLinks.type), desc(animeSongLinks.number));
|
||||
|
||||
return {
|
||||
anime,
|
||||
|
||||
@@ -14,21 +14,21 @@ import amqGroupsJson from "../../../data/amq-groups.json" with { type: "json" };
|
||||
import amqSongsJson from "../../../data/amq-songs.json" with { type: "json" };
|
||||
import { db } from "./index";
|
||||
import {
|
||||
animeGenresTable,
|
||||
animeNamesTable,
|
||||
animeSongLinksTable,
|
||||
animeTable,
|
||||
animeTagsTable,
|
||||
artistAltNamesTable,
|
||||
artistGroupsTable,
|
||||
artistsTable,
|
||||
genresTable,
|
||||
groupAltNamesTable,
|
||||
groupArtistMembersTable,
|
||||
groupGroupMembersTable,
|
||||
groupsTable,
|
||||
songsTable,
|
||||
tagsTable,
|
||||
anime,
|
||||
animeGenres,
|
||||
animeNames,
|
||||
animeSongLinks,
|
||||
animeTags,
|
||||
artistAltNames,
|
||||
artistGroups,
|
||||
artists,
|
||||
genres,
|
||||
groupAltNames,
|
||||
groupArtistMembers,
|
||||
groupGroupMembers,
|
||||
groups,
|
||||
songs,
|
||||
tags,
|
||||
} from "./schema";
|
||||
|
||||
/**
|
||||
@@ -169,15 +169,15 @@ export async function importAmqData(
|
||||
);
|
||||
}
|
||||
|
||||
const anime = animeParsed.data;
|
||||
const songs = songsParsed.data;
|
||||
const artists = artistsParsed.data;
|
||||
const groups = groupsParsed.data;
|
||||
const animeData = animeParsed.data;
|
||||
const songsData = songsParsed.data;
|
||||
const artistsData = artistsParsed.data;
|
||||
const groupsData = groupsParsed.data;
|
||||
|
||||
if (verbose) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(
|
||||
`AMQ import: ${anime.length} anime, ${songs.length} songs, ${artists.length} artists, ${groups.length} groups`,
|
||||
`AMQ import: ${animeData.length} anime, ${songsData.length} songs, ${artistsData.length} artists, ${groupsData.length} groups`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -185,45 +185,45 @@ export async function importAmqData(
|
||||
db.transaction(() => {
|
||||
if (wipeFirst) {
|
||||
// Child tables first, then parents (respect FKs)
|
||||
db.delete(animeSongLinksTable).run();
|
||||
db.delete(animeNamesTable).run();
|
||||
db.delete(animeGenresTable).run();
|
||||
db.delete(animeTagsTable).run();
|
||||
db.delete(animeSongLinks).run();
|
||||
db.delete(animeNames).run();
|
||||
db.delete(animeGenres).run();
|
||||
db.delete(animeTags).run();
|
||||
|
||||
// artist/group graph tables
|
||||
db.delete(groupGroupMembersTable).run();
|
||||
db.delete(groupArtistMembersTable).run();
|
||||
db.delete(artistGroupsTable).run();
|
||||
db.delete(groupAltNamesTable).run();
|
||||
db.delete(artistAltNamesTable).run();
|
||||
db.delete(groupGroupMembers).run();
|
||||
db.delete(groupArtistMembers).run();
|
||||
db.delete(artistGroups).run();
|
||||
db.delete(groupAltNames).run();
|
||||
db.delete(artistAltNames).run();
|
||||
|
||||
db.delete(animeTable).run();
|
||||
db.delete(anime).run();
|
||||
|
||||
// songs referenced by anime_song_links; delete after links wiped
|
||||
db.delete(songsTable).run();
|
||||
db.delete(songs).run();
|
||||
|
||||
// groups referenced by graph tables
|
||||
db.delete(groupsTable).run();
|
||||
db.delete(groups).run();
|
||||
|
||||
// artists referenced by graph tables
|
||||
db.delete(artistsTable).run();
|
||||
db.delete(artists).run();
|
||||
}
|
||||
|
||||
// 2a) Insert artists (core)
|
||||
{
|
||||
const artistRows = artists.map((a) => ({
|
||||
const artistRows = artistsData.map((a) => ({
|
||||
songArtistId: a.songArtistId,
|
||||
name: a.name,
|
||||
}));
|
||||
|
||||
for (const batch of chunk(artistRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(artistsTable)
|
||||
db.insert(artists)
|
||||
.values(batch)
|
||||
.onConflictDoUpdate({
|
||||
target: artistsTable.songArtistId,
|
||||
target: artists.songArtistId,
|
||||
set: {
|
||||
name: artistsTable.name,
|
||||
name: artists.name,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
@@ -232,19 +232,19 @@ export async function importAmqData(
|
||||
|
||||
// 2a.1) Insert groups (core)
|
||||
{
|
||||
const groupRows = groups.map((g) => ({
|
||||
const groupRows = groupsData.map((g) => ({
|
||||
songGroupId: g.songGroupId,
|
||||
name: g.name,
|
||||
}));
|
||||
|
||||
for (const batch of chunk(groupRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(groupsTable)
|
||||
db.insert(groups)
|
||||
.values(batch)
|
||||
.onConflictDoUpdate({
|
||||
target: groupsTable.songGroupId,
|
||||
target: groups.songGroupId,
|
||||
set: {
|
||||
name: groupsTable.name,
|
||||
name: groups.name,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
@@ -255,14 +255,14 @@ export async function importAmqData(
|
||||
// For these join tables, easiest/most consistent is replace-all (delete then insert),
|
||||
// since they’re derived arrays and can change over time.
|
||||
{
|
||||
db.delete(artistGroupsTable).run();
|
||||
db.delete(groupArtistMembersTable).run();
|
||||
db.delete(groupGroupMembersTable).run();
|
||||
db.delete(artistAltNamesTable).run();
|
||||
db.delete(groupAltNamesTable).run();
|
||||
db.delete(artistGroups).run();
|
||||
db.delete(groupArtistMembers).run();
|
||||
db.delete(groupGroupMembers).run();
|
||||
db.delete(artistAltNames).run();
|
||||
db.delete(groupAltNames).run();
|
||||
|
||||
// artist -> groups
|
||||
const artistGroupRows = artists.flatMap((a) =>
|
||||
const artistGroupRows = artistsData.flatMap((a) =>
|
||||
a.inGroups.map((songGroupId) => ({
|
||||
songArtistId: a.songArtistId,
|
||||
songGroupId,
|
||||
@@ -270,11 +270,11 @@ export async function importAmqData(
|
||||
);
|
||||
for (const batch of chunk(artistGroupRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(artistGroupsTable).values(batch).run();
|
||||
db.insert(artistGroups).values(batch).run();
|
||||
}
|
||||
|
||||
// group -> artist members
|
||||
const groupArtistMemberRows = groups.flatMap((g) =>
|
||||
const groupArtistMemberRows = groupsData.flatMap((g) =>
|
||||
g.artistMembers.map((songArtistId) => ({
|
||||
songGroupId: g.songGroupId,
|
||||
songArtistId,
|
||||
@@ -282,11 +282,11 @@ export async function importAmqData(
|
||||
);
|
||||
for (const batch of chunk(groupArtistMemberRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(groupArtistMembersTable).values(batch).run();
|
||||
db.insert(groupArtistMembers).values(batch).run();
|
||||
}
|
||||
|
||||
// group -> group members
|
||||
const groupGroupMemberRows = groups.flatMap((g) =>
|
||||
const groupGroupMemberRows = groupsData.flatMap((g) =>
|
||||
g.groupMembers.map((memberSongGroupId) => ({
|
||||
songGroupId: g.songGroupId,
|
||||
memberSongGroupId,
|
||||
@@ -294,11 +294,11 @@ export async function importAmqData(
|
||||
);
|
||||
for (const batch of chunk(groupGroupMemberRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(groupGroupMembersTable).values(batch).run();
|
||||
db.insert(groupGroupMembers).values(batch).run();
|
||||
}
|
||||
|
||||
// artist alt names: { songArtistId, name } (stored as altSongArtistId in DB)
|
||||
const artistAltNameRows = artists.flatMap((a) =>
|
||||
const artistAltNameRows = artistsData.flatMap((a) =>
|
||||
a.altNames.map((alt) => ({
|
||||
songArtistId: a.songArtistId,
|
||||
altSongArtistId: alt.songArtistId,
|
||||
@@ -307,11 +307,11 @@ export async function importAmqData(
|
||||
);
|
||||
for (const batch of chunk(artistAltNameRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(artistAltNamesTable).values(batch).run();
|
||||
db.insert(artistAltNames).values(batch).run();
|
||||
}
|
||||
|
||||
// group alt names: { songGroupId, name } where object.songGroupId is the context
|
||||
const groupAltNameRows = groups.flatMap((g) =>
|
||||
const groupAltNameRows = groupsData.flatMap((g) =>
|
||||
g.altNames.map((alt) => ({
|
||||
songGroupId: g.songGroupId,
|
||||
contextSongGroupId: alt.songGroupId,
|
||||
@@ -320,13 +320,13 @@ export async function importAmqData(
|
||||
);
|
||||
for (const batch of chunk(groupAltNameRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(groupAltNamesTable).values(batch).run();
|
||||
db.insert(groupAltNames).values(batch).run();
|
||||
}
|
||||
}
|
||||
|
||||
// 2b) Insert songs
|
||||
{
|
||||
const songRows = songs.map((s) => ({
|
||||
const songRows = songsData.map((s) => ({
|
||||
annSongId: s.annSongId,
|
||||
songId: s.songId,
|
||||
name: s.name,
|
||||
@@ -345,21 +345,21 @@ export async function importAmqData(
|
||||
|
||||
for (const batch of chunk(songRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(songsTable)
|
||||
db.insert(songs)
|
||||
.values(batch)
|
||||
.onConflictDoUpdate({
|
||||
target: songsTable.annSongId,
|
||||
target: songs.annSongId,
|
||||
set: {
|
||||
songId: songsTable.songId,
|
||||
name: songsTable.name,
|
||||
category: songsTable.category,
|
||||
fileName: songsTable.fileName,
|
||||
songArtistId: songsTable.songArtistId,
|
||||
songGroupId: songsTable.songGroupId,
|
||||
composerArtistId: songsTable.composerArtistId,
|
||||
composerGroupId: songsTable.composerGroupId,
|
||||
arrangerArtistId: songsTable.arrangerArtistId,
|
||||
arrangerGroupId: songsTable.arrangerGroupId,
|
||||
songId: songs.songId,
|
||||
name: songs.name,
|
||||
category: songs.category,
|
||||
fileName: songs.fileName,
|
||||
songArtistId: songs.songArtistId,
|
||||
songGroupId: songs.songGroupId,
|
||||
composerArtistId: songs.composerArtistId,
|
||||
composerGroupId: songs.composerGroupId,
|
||||
arrangerArtistId: songs.arrangerArtistId,
|
||||
arrangerGroupId: songs.arrangerGroupId,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
@@ -368,7 +368,7 @@ export async function importAmqData(
|
||||
|
||||
// 2c) Insert anime and its normalized children
|
||||
{
|
||||
const animeRows = anime.map((a) => ({
|
||||
const animeRows = animeData.map((a) => ({
|
||||
annId: a.annId,
|
||||
aniListId: a.aniListId,
|
||||
malId: a.malId,
|
||||
@@ -387,24 +387,24 @@ export async function importAmqData(
|
||||
|
||||
for (const batch of chunk(animeRows, batchSize)) {
|
||||
if (batch.length === 0) continue;
|
||||
db.insert(animeTable)
|
||||
db.insert(anime)
|
||||
.values(batch)
|
||||
.onConflictDoUpdate({
|
||||
target: animeTable.annId,
|
||||
target: anime.annId,
|
||||
set: {
|
||||
aniListId: animeTable.aniListId,
|
||||
malId: animeTable.malId,
|
||||
kitsuId: animeTable.kitsuId,
|
||||
categoryName: animeTable.categoryName,
|
||||
categoryNumber: animeTable.categoryNumber,
|
||||
mainName: animeTable.mainName,
|
||||
mainNameEn: animeTable.mainNameEn,
|
||||
mainNameJa: animeTable.mainNameJa,
|
||||
year: animeTable.year,
|
||||
seasonId: animeTable.seasonId,
|
||||
opCount: animeTable.opCount,
|
||||
edCount: animeTable.edCount,
|
||||
insertCount: animeTable.insertCount,
|
||||
aniListId: anime.aniListId,
|
||||
malId: anime.malId,
|
||||
kitsuId: anime.kitsuId,
|
||||
categoryName: anime.categoryName,
|
||||
categoryNumber: anime.categoryNumber,
|
||||
mainName: anime.mainName,
|
||||
mainNameEn: anime.mainNameEn,
|
||||
mainNameJa: anime.mainNameJa,
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
opCount: anime.opCount,
|
||||
edCount: anime.edCount,
|
||||
insertCount: anime.insertCount,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
@@ -412,23 +412,17 @@ export async function importAmqData(
|
||||
|
||||
// For child tables, simplest is: delete existing for these annIds then insert fresh.
|
||||
// (Safer than trying to upsert composite unique constraints for each child row.)
|
||||
for (const a of anime) {
|
||||
db.delete(animeNamesTable)
|
||||
.where(eq(animeNamesTable.annId, a.annId))
|
||||
.run();
|
||||
db.delete(animeGenresTable)
|
||||
.where(eq(animeGenresTable.annId, a.annId))
|
||||
.run();
|
||||
db.delete(animeTagsTable)
|
||||
.where(eq(animeTagsTable.annId, a.annId))
|
||||
.run();
|
||||
db.delete(animeSongLinksTable)
|
||||
.where(eq(animeSongLinksTable.annId, a.annId))
|
||||
for (const a of animeData) {
|
||||
db.delete(animeNames).where(eq(animeNames.annId, a.annId)).run();
|
||||
db.delete(animeGenres).where(eq(animeGenres.annId, a.annId)).run();
|
||||
db.delete(animeTags).where(eq(animeTags.annId, a.annId)).run();
|
||||
db.delete(animeSongLinks)
|
||||
.where(eq(animeSongLinks.annId, a.annId))
|
||||
.run();
|
||||
|
||||
// names
|
||||
if (a.names.length) {
|
||||
db.insert(animeNamesTable)
|
||||
db.insert(animeNames)
|
||||
.values(
|
||||
a.names.map((n) => ({
|
||||
annId: a.annId,
|
||||
@@ -442,13 +436,13 @@ export async function importAmqData(
|
||||
// genres
|
||||
if (a.genres.length) {
|
||||
// Ensure lookup rows exist (string PK)
|
||||
db.insert(genresTable)
|
||||
db.insert(genres)
|
||||
.values(a.genres.map((g) => ({ name: g })))
|
||||
.onConflictDoNothing()
|
||||
.run();
|
||||
|
||||
// Insert relations
|
||||
db.insert(animeGenresTable)
|
||||
db.insert(animeGenres)
|
||||
.values(
|
||||
a.genres.map((g) => ({
|
||||
annId: a.annId,
|
||||
@@ -461,13 +455,13 @@ export async function importAmqData(
|
||||
// tags
|
||||
if (a.tags.length) {
|
||||
// Ensure lookup rows exist (string PK)
|
||||
db.insert(tagsTable)
|
||||
db.insert(tags)
|
||||
.values(a.tags.map((t) => ({ name: t })))
|
||||
.onConflictDoNothing()
|
||||
.run();
|
||||
|
||||
// Insert relations
|
||||
db.insert(animeTagsTable)
|
||||
db.insert(animeTags)
|
||||
.values(
|
||||
a.tags.map((t) => ({
|
||||
annId: a.annId,
|
||||
@@ -479,7 +473,7 @@ export async function importAmqData(
|
||||
|
||||
// song links
|
||||
if (a.songLinks.length) {
|
||||
db.insert(animeSongLinksTable)
|
||||
db.insert(animeSongLinks)
|
||||
.values(
|
||||
a.songLinks.map((l) => ({
|
||||
annId: a.annId,
|
||||
|
||||
@@ -1,87 +1,84 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { animeTable } from "./tables/anime";
|
||||
import { animeGenresTable } from "./tables/anime-genres";
|
||||
import { animeNamesTable } from "./tables/anime-names";
|
||||
import { animeSongLinksTable } from "./tables/anime-song-links";
|
||||
import { animeTagsTable } from "./tables/anime-tags";
|
||||
import { artistAltNamesTable } from "./tables/artist-alt-names";
|
||||
import { artistGroupsTable } from "./tables/artist-groups";
|
||||
import { artistsTable } from "./tables/artists";
|
||||
import { genresTable } from "./tables/genres";
|
||||
import { groupAltNamesTable } from "./tables/group-alt-names";
|
||||
import { groupArtistMembersTable } from "./tables/group-artist-members";
|
||||
import { groupGroupMembersTable } from "./tables/group-group-members";
|
||||
import { groupsTable } from "./tables/groups";
|
||||
import { songsTable } from "./tables/songs";
|
||||
import { tagsTable } from "./tables/tags";
|
||||
import { anime } from "./tables/anime";
|
||||
import { animeGenres } from "./tables/anime-genres";
|
||||
import { animeNames } from "./tables/anime-names";
|
||||
import { animeSongLinks } from "./tables/anime-song-links";
|
||||
import { animeTags } from "./tables/anime-tags";
|
||||
import { artistAltNames } from "./tables/artist-alt-names";
|
||||
import { artistGroups } from "./tables/artist-groups";
|
||||
import { artists } from "./tables/artists";
|
||||
import { genres } from "./tables/genres";
|
||||
import { groupAltNames } from "./tables/group-alt-names";
|
||||
import { groupArtistMembers } from "./tables/group-artist-members";
|
||||
import { groupGroupMembers } from "./tables/group-group-members";
|
||||
import { groups } from "./tables/groups";
|
||||
import { songs } from "./tables/songs";
|
||||
import { tags } from "./tables/tags";
|
||||
|
||||
// ----------------------
|
||||
// Relations (optional but helpful for Drizzle queries)
|
||||
// ----------------------
|
||||
|
||||
export const animeRelations = relations(animeTable, ({ many }) => ({
|
||||
names: many(animeNamesTable),
|
||||
genres: many(animeGenresTable),
|
||||
tags: many(animeTagsTable),
|
||||
songLinks: many(animeSongLinksTable),
|
||||
export const animeRelations = relations(anime, ({ many }) => ({
|
||||
names: many(animeNames),
|
||||
genres: many(animeGenres),
|
||||
tags: many(animeTags),
|
||||
songLinks: many(animeSongLinks),
|
||||
}));
|
||||
|
||||
export const songRelations = relations(songsTable, ({ many }) => ({
|
||||
animeLinks: many(animeSongLinksTable),
|
||||
export const songRelations = relations(songs, ({ many }) => ({
|
||||
animeLinks: many(animeSongLinks),
|
||||
}));
|
||||
|
||||
export const artistRelations = relations(artistsTable, ({ many }) => ({
|
||||
inGroups: many(artistGroupsTable),
|
||||
altNames: many(artistAltNamesTable),
|
||||
groupMemberships: many(groupArtistMembersTable),
|
||||
export const artistRelations = relations(artists, ({ many }) => ({
|
||||
inGroups: many(artistGroups),
|
||||
altNames: many(artistAltNames),
|
||||
groupMemberships: many(groupArtistMembers),
|
||||
}));
|
||||
|
||||
export const groupRelations = relations(groupsTable, ({ many }) => ({
|
||||
artists: many(artistGroupsTable),
|
||||
artistMembers: many(groupArtistMembersTable),
|
||||
groupMembers: many(groupGroupMembersTable),
|
||||
altNames: many(groupAltNamesTable),
|
||||
export const groupRelations = relations(groups, ({ many }) => ({
|
||||
artists: many(artistGroups),
|
||||
artistMembers: many(groupArtistMembers),
|
||||
groupMembers: many(groupGroupMembers),
|
||||
altNames: many(groupAltNames),
|
||||
}));
|
||||
|
||||
export const animeNamesRelations = relations(animeNamesTable, ({ one }) => ({
|
||||
anime: one(animeTable, {
|
||||
fields: [animeNamesTable.annId],
|
||||
references: [animeTable.annId],
|
||||
export const animeNamesRelations = relations(animeNames, ({ one }) => ({
|
||||
anime: one(anime, {
|
||||
fields: [animeNames.annId],
|
||||
references: [anime.annId],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const animeGenresRelations = relations(animeGenresTable, ({ one }) => ({
|
||||
anime: one(animeTable, {
|
||||
fields: [animeGenresTable.annId],
|
||||
references: [animeTable.annId],
|
||||
export const animeGenresRelations = relations(animeGenres, ({ one }) => ({
|
||||
anime: one(anime, {
|
||||
fields: [animeGenres.annId],
|
||||
references: [anime.annId],
|
||||
}),
|
||||
genre: one(genresTable, {
|
||||
fields: [animeGenresTable.genreName],
|
||||
references: [genresTable.name],
|
||||
genre: one(genres, {
|
||||
fields: [animeGenres.genreName],
|
||||
references: [genres.name],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const animeTagsRelations = relations(animeTagsTable, ({ one }) => ({
|
||||
anime: one(animeTable, {
|
||||
fields: [animeTagsTable.annId],
|
||||
references: [animeTable.annId],
|
||||
export const animeTagsRelations = relations(animeTags, ({ one }) => ({
|
||||
anime: one(anime, {
|
||||
fields: [animeTags.annId],
|
||||
references: [anime.annId],
|
||||
}),
|
||||
tag: one(tagsTable, {
|
||||
fields: [animeTagsTable.tagName],
|
||||
references: [tagsTable.name],
|
||||
tag: one(tags, {
|
||||
fields: [animeTags.tagName],
|
||||
references: [tags.name],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const animeSongLinksRelations = relations(
|
||||
animeSongLinksTable,
|
||||
({ one }) => ({
|
||||
anime: one(animeTable, {
|
||||
fields: [animeSongLinksTable.annId],
|
||||
references: [animeTable.annId],
|
||||
export const animeSongLinksRelations = relations(animeSongLinks, ({ one }) => ({
|
||||
anime: one(anime, {
|
||||
fields: [animeSongLinks.annId],
|
||||
references: [anime.annId],
|
||||
}),
|
||||
song: one(songsTable, {
|
||||
fields: [animeSongLinksTable.annSongId],
|
||||
references: [songsTable.annSongId],
|
||||
song: one(songs, {
|
||||
fields: [animeSongLinks.annSongId],
|
||||
references: [songs.annSongId],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}));
|
||||
|
||||
@@ -5,23 +5,23 @@ import {
|
||||
sqliteTable,
|
||||
text,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { animeTable } from "./anime";
|
||||
import { genresTable } from "./genres";
|
||||
import { anime } from "./anime";
|
||||
import { genres } from "./genres";
|
||||
|
||||
/**
|
||||
* Join table: Anime -> Genres
|
||||
*
|
||||
* Source: AmqAnimeSchema.genres (string[])
|
||||
*/
|
||||
export const animeGenresTable = sqliteTable(
|
||||
export const animeGenres = sqliteTable(
|
||||
"anime_genres",
|
||||
{
|
||||
annId: integer("ann_id")
|
||||
.notNull()
|
||||
.references(() => animeTable.annId, { onDelete: "cascade" }),
|
||||
.references(() => anime.annId, { onDelete: "cascade" }),
|
||||
genreName: text("genre_name")
|
||||
.notNull()
|
||||
.references(() => genresTable.name, { onDelete: "cascade" }),
|
||||
.references(() => genres.name, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey({
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
text,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { animeTable } from "./anime";
|
||||
import { anime } from "./anime";
|
||||
|
||||
/**
|
||||
* Additional localized/alternative names for an anime.
|
||||
@@ -14,14 +14,14 @@ import { animeTable } from "./anime";
|
||||
* - language: "EN" | "JA" (per source)
|
||||
* - name: string
|
||||
*/
|
||||
export const animeNamesTable = sqliteTable(
|
||||
export const animeNames = sqliteTable(
|
||||
"anime_names",
|
||||
{
|
||||
id: integer("id").notNull().primaryKey({ autoIncrement: true }),
|
||||
|
||||
annId: integer("ann_id")
|
||||
.notNull()
|
||||
.references(() => animeTable.annId, { onDelete: "cascade" }),
|
||||
.references(() => anime.annId, { onDelete: "cascade" }),
|
||||
|
||||
/** "EN" | "JA" per source */
|
||||
language: text("language").notNull(),
|
||||
|
||||
@@ -4,24 +4,24 @@ import {
|
||||
primaryKey,
|
||||
sqliteTable,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { animeTable } from "./anime";
|
||||
import { songsTable } from "./songs";
|
||||
import { anime } from "./anime";
|
||||
import { songs } from "./songs";
|
||||
|
||||
/**
|
||||
* Join table: Anime <-> Songs links
|
||||
*
|
||||
* Source: AmqAnimeSchema.songLinks (AmqSongLink[])
|
||||
*/
|
||||
export const animeSongLinksTable = sqliteTable(
|
||||
export const animeSongLinks = sqliteTable(
|
||||
"anime_song_links",
|
||||
{
|
||||
annId: integer("ann_id")
|
||||
.notNull()
|
||||
.references(() => animeTable.annId, { onDelete: "cascade" }),
|
||||
.references(() => anime.annId, { onDelete: "cascade" }),
|
||||
|
||||
annSongId: integer("ann_song_id")
|
||||
.notNull()
|
||||
.references(() => songsTable.annSongId, { onDelete: "cascade" }),
|
||||
.references(() => songs.annSongId, { onDelete: "cascade" }),
|
||||
|
||||
/** 1(OP) | 2(ED) | 3(INS) per SongLinkType */
|
||||
type: integer("type").notNull(),
|
||||
|
||||
@@ -5,23 +5,23 @@ import {
|
||||
sqliteTable,
|
||||
text,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { animeTable } from "./anime";
|
||||
import { tagsTable } from "./tags";
|
||||
import { anime } from "./anime";
|
||||
import { tags } from "./tags";
|
||||
|
||||
/**
|
||||
* Join table: Anime -> Tags
|
||||
*
|
||||
* Source: AmqAnimeSchema.tags (string[])
|
||||
*/
|
||||
export const animeTagsTable = sqliteTable(
|
||||
export const animeTags = sqliteTable(
|
||||
"anime_tags",
|
||||
{
|
||||
annId: integer("ann_id")
|
||||
.notNull()
|
||||
.references(() => animeTable.annId, { onDelete: "cascade" }),
|
||||
.references(() => anime.annId, { onDelete: "cascade" }),
|
||||
tagName: text("tag_name")
|
||||
.notNull()
|
||||
.references(() => tagsTable.name, { onDelete: "cascade" }),
|
||||
.references(() => tags.name, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey({
|
||||
|
||||
@@ -8,7 +8,7 @@ import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
*
|
||||
* Source: AmqAnimeSchema
|
||||
*/
|
||||
export const animeTable = sqliteTable(
|
||||
export const anime = sqliteTable(
|
||||
"anime",
|
||||
{
|
||||
/** AMQ anime ID */
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
text,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { artistsTable } from "./artists";
|
||||
import { artists } from "./artists";
|
||||
|
||||
/**
|
||||
* Alternative names for artists.
|
||||
@@ -14,7 +14,7 @@ import { artistsTable } from "./artists";
|
||||
*
|
||||
* Interpreted as: artist `songArtistId` is also known as `name` (optionally via altSongArtistId link).
|
||||
*/
|
||||
export const artistAltNamesTable = sqliteTable(
|
||||
export const artistAltNames = sqliteTable(
|
||||
"artist_alt_names",
|
||||
{
|
||||
id: integer("id").notNull().primaryKey({ autoIncrement: true }),
|
||||
@@ -24,7 +24,7 @@ export const artistAltNamesTable = sqliteTable(
|
||||
*/
|
||||
songArtistId: integer("song_artist_id")
|
||||
.notNull()
|
||||
.references(() => artistsTable.songArtistId, {
|
||||
.references(() => artists.songArtistId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
|
||||
@@ -36,7 +36,7 @@ export const artistAltNamesTable = sqliteTable(
|
||||
*/
|
||||
altSongArtistId: integer("alt_song_artist_id")
|
||||
.notNull()
|
||||
.references(() => artistsTable.songArtistId, {
|
||||
.references(() => artists.songArtistId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
|
||||
|
||||
@@ -4,25 +4,25 @@ import {
|
||||
primaryKey,
|
||||
sqliteTable,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { artistsTable } from "./artists";
|
||||
import { groupsTable } from "./groups";
|
||||
import { artists } from "./artists";
|
||||
import { groups } from "./groups";
|
||||
|
||||
/**
|
||||
* Join table: Artist -> Groups membership
|
||||
*
|
||||
* Source: AmqArtistSchema.inGroups
|
||||
*/
|
||||
export const artistGroupsTable = sqliteTable(
|
||||
export const artistGroups = sqliteTable(
|
||||
"artist_groups",
|
||||
{
|
||||
songArtistId: integer("song_artist_id")
|
||||
.notNull()
|
||||
.references(() => artistsTable.songArtistId, {
|
||||
.references(() => artists.songArtistId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
songGroupId: integer("song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
*
|
||||
* Source: AmqArtistSchema
|
||||
*/
|
||||
export const artistsTable = sqliteTable(
|
||||
export const artists = sqliteTable(
|
||||
"artists",
|
||||
{
|
||||
/** AMQ songArtistId */
|
||||
|
||||
@@ -5,7 +5,7 @@ import { index, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
*
|
||||
* Source: AmqAnimeSchema.genres (string[])
|
||||
*/
|
||||
export const genresTable = sqliteTable(
|
||||
export const genres = sqliteTable(
|
||||
"genres",
|
||||
{
|
||||
/** Primary key is the genre string itself */
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
text,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { groupsTable } from "./groups";
|
||||
import { groups } from "./groups";
|
||||
|
||||
/**
|
||||
* Alternative names for groups.
|
||||
@@ -16,7 +16,7 @@ import { groupsTable } from "./groups";
|
||||
* `songGroupId` is effectively the *context group* the alias is associated with.
|
||||
* We persist it as `contextSongGroupId` to make the meaning explicit.
|
||||
*/
|
||||
export const groupAltNamesTable = sqliteTable(
|
||||
export const groupAltNames = sqliteTable(
|
||||
"group_alt_names",
|
||||
{
|
||||
id: integer("id").notNull().primaryKey({ autoIncrement: true }),
|
||||
@@ -26,7 +26,7 @@ export const groupAltNamesTable = sqliteTable(
|
||||
*/
|
||||
songGroupId: integer("song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
|
||||
/**
|
||||
* Context group the alias is associated with.
|
||||
@@ -34,7 +34,7 @@ export const groupAltNamesTable = sqliteTable(
|
||||
*/
|
||||
contextSongGroupId: integer("context_song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
|
||||
name: text("name").notNull(),
|
||||
},
|
||||
|
||||
@@ -4,23 +4,23 @@ import {
|
||||
primaryKey,
|
||||
sqliteTable,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { artistsTable } from "./artists";
|
||||
import { groupsTable } from "./groups";
|
||||
import { artists } from "./artists";
|
||||
import { groups } from "./groups";
|
||||
|
||||
/**
|
||||
* Join table: Group -> Artist members
|
||||
*
|
||||
* Source: AmqGroupSchema.artistMembers
|
||||
*/
|
||||
export const groupArtistMembersTable = sqliteTable(
|
||||
export const groupArtistMembers = sqliteTable(
|
||||
"group_artist_members",
|
||||
{
|
||||
songGroupId: integer("song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
songArtistId: integer("song_artist_id")
|
||||
.notNull()
|
||||
.references(() => artistsTable.songArtistId, {
|
||||
.references(() => artists.songArtistId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -4,22 +4,22 @@ import {
|
||||
primaryKey,
|
||||
sqliteTable,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { groupsTable } from "./groups";
|
||||
import { groups } from "./groups";
|
||||
|
||||
/**
|
||||
* Join table: Group -> Group members
|
||||
*
|
||||
* Source: AmqGroupSchema.groupMembers
|
||||
*/
|
||||
export const groupGroupMembersTable = sqliteTable(
|
||||
export const groupGroupMembers = sqliteTable(
|
||||
"group_group_members",
|
||||
{
|
||||
songGroupId: integer("song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
memberSongGroupId: integer("member_song_group_id")
|
||||
.notNull()
|
||||
.references(() => groupsTable.songGroupId, { onDelete: "cascade" }),
|
||||
.references(() => groups.songGroupId, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
*
|
||||
* Source: AmqGroupSchema
|
||||
*/
|
||||
export const groupsTable = sqliteTable(
|
||||
export const groups = sqliteTable(
|
||||
"groups",
|
||||
{
|
||||
/** AMQ songGroupId */
|
||||
|
||||
@@ -5,15 +5,15 @@ import {
|
||||
sqliteTable,
|
||||
text,
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { artistsTable } from "./artists";
|
||||
import { groupsTable } from "./groups";
|
||||
import { artists } from "./artists";
|
||||
import { groups } from "./groups";
|
||||
|
||||
/**
|
||||
* Core `songs` table.
|
||||
*
|
||||
* Source: AmqSongSchema
|
||||
*/
|
||||
export const songsTable = sqliteTable(
|
||||
export const songs = sqliteTable(
|
||||
"songs",
|
||||
{
|
||||
/** AMQ annSongId (ANN song id) */
|
||||
@@ -44,31 +44,30 @@ export const songsTable = sqliteTable(
|
||||
* These reference existing `artists` / `groups` rows.
|
||||
*/
|
||||
songArtistId: integer("song_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
songGroupId: integer("song_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
() => artists.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
songGroupId: integer("song_group_id").references(() => groups.songGroupId, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
/**
|
||||
* Additional contributor ids (nullable in source)
|
||||
*/
|
||||
composerArtistId: integer("composer_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
() => artists.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
composerGroupId: integer("composer_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
() => groups.songGroupId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
arrangerArtistId: integer("arranger_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
() => artists.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
arrangerGroupId: integer("arranger_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
() => groups.songGroupId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ import { index, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
*
|
||||
* Source: AmqAnimeSchema.tags (string[])
|
||||
*/
|
||||
export const tagsTable = sqliteTable(
|
||||
export const tags = sqliteTable(
|
||||
"tags",
|
||||
{
|
||||
/** Primary key is the tag string itself */
|
||||
|
||||
Reference in New Issue
Block a user