db: remove table suffix from schemas

This commit is contained in:
2026-02-05 19:28:30 -08:00
parent 88218b3567
commit 53f91facc9
18 changed files with 249 additions and 279 deletions

View File

@@ -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,

View File

@@ -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 theyre 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,

View File

@@ -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],
}),
song: one(songsTable, {
fields: [animeSongLinksTable.annSongId],
references: [songsTable.annSongId],
}),
export const animeSongLinksRelations = relations(animeSongLinks, ({ one }) => ({
anime: one(anime, {
fields: [animeSongLinks.annId],
references: [anime.annId],
}),
);
song: one(songs, {
fields: [animeSongLinks.annSongId],
references: [songs.annSongId],
}),
}));

View File

@@ -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({

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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({

View File

@@ -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 */

View File

@@ -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",
}),

View File

@@ -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({

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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(),
},

View File

@@ -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",
}),
},

View File

@@ -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({

View File

@@ -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 */

View File

@@ -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" },
),
},

View File

@@ -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 */