refactor(db): remove user_id foreign key from user_tts_chars

Remove the foreign key constraint referencing the user table in both
Postgres and SQLite schemas. This decouples the usage tracking from
the primary user table.
This commit is contained in:
Richard R 2026-02-16 17:29:26 -07:00
parent fc24b31cc3
commit f58a2b690d
8 changed files with 11 additions and 41 deletions

View file

@ -139,7 +139,6 @@ ALTER TABLE "audiobooks" ADD CONSTRAINT "audiobooks_user_id_user_id_fk" FOREIGN
ALTER TABLE "documents" ADD CONSTRAINT "documents_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_document_progress" ADD CONSTRAINT "user_document_progress_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_tts_chars" ADD CONSTRAINT "user_tts_chars_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "idx_document_previews_status_lease" ON "document_previews" USING btree ("status","lease_until_ms");--> statement-breakpoint

View file

@ -1,5 +1,5 @@
{
"id": "ad9a34b6-48d9-4e3a-95cd-38941cb2e055",
"id": "ed6cbfef-d016-4265-999b-239f10f9e4e1",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
@ -688,21 +688,7 @@
"with": {}
}
},
"foreignKeys": {
"user_tts_chars_user_id_user_id_fk": {
"name": "user_tts_chars_user_id_user_id_fk",
"tableFrom": "user_tts_chars",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"user_tts_chars_user_id_date_pk": {
"name": "user_tts_chars_user_id_date_pk",

View file

@ -5,8 +5,8 @@
{
"idx": 0,
"version": "7",
"when": 1771188820113,
"tag": "0000_famous_justin_hammer",
"when": 1771284020206,
"tag": "0000_fearless_vargas",
"breakpoints": true
}
]

View file

@ -91,8 +91,7 @@ CREATE TABLE `user_tts_chars` (
`char_count` integer DEFAULT 0,
`created_at` integer DEFAULT (cast(strftime('%s','now') as int) * 1000),
`updated_at` integer DEFAULT (cast(strftime('%s','now') as int) * 1000),
PRIMARY KEY(`user_id`, `date`),
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
PRIMARY KEY(`user_id`, `date`)
);
--> statement-breakpoint
CREATE INDEX `idx_user_tts_chars_date` ON `user_tts_chars` (`date`);--> statement-breakpoint

View file

@ -1,7 +1,7 @@
{
"version": "6",
"dialect": "sqlite",
"id": "d7c41fe0-7d08-42af-8f53-d95fd35776c2",
"id": "2406985e-1b41-49e8-9add-304814080095",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"audiobook_chapters": {
@ -673,21 +673,7 @@
"isUnique": false
}
},
"foreignKeys": {
"user_tts_chars_user_id_user_id_fk": {
"name": "user_tts_chars_user_id_user_id_fk",
"tableFrom": "user_tts_chars",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"user_tts_chars_user_id_date_pk": {
"columns": [

View file

@ -5,8 +5,8 @@
{
"idx": 0,
"version": "6",
"when": 1771188819810,
"tag": "0000_nervous_preak",
"when": 1771284019941,
"tag": "0000_lucky_inertia",
"breakpoints": true
}
]

View file

@ -51,7 +51,7 @@ export const audiobookChapters = pgTable('audiobook_chapters', {
// defined here. Only application-specific tables belong in this file.
export const userTtsChars = pgTable("user_tts_chars", {
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
userId: text('user_id').notNull(),
date: date('date').notNull(),
charCount: bigint('char_count', { mode: 'number' }).default(0),
createdAt: timestamp('created_at').defaultNow(),

View file

@ -52,7 +52,7 @@ export const audiobookChapters = sqliteTable('audiobook_chapters', {
// defined here. Only application-specific tables belong in this file.
export const userTtsChars = sqliteTable("user_tts_chars", {
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
userId: text('user_id').notNull(),
date: text('date').notNull(), // SQLite doesn't have native DATE type, text YYYY-MM-DD is standard
charCount: integer('char_count').default(0),
createdAt: integer('created_at').default(sql`(cast(strftime('%s','now') as int) * 1000)`),