refactor(db): recipe_views -> recipe_view, TIMESTAMP-Konsistenz
Code-Review-Findings nachgezogen: Tabellen-Konvention im Repo ist singular (profile, recipe, favorite, cooking_log, thumbnail_cache), deshalb recipe_view statt recipe_views; Index analog umbenannt. last_viewed_at auf TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP gewechselt — matcht den Rest des Schemas. Header-Kommentar + notnull-Assertion fuer recipe_id ergaenzt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
CREATE TABLE recipe_views (
|
-- Merkt je Profil, wann ein Rezept zuletzt angesehen wurde.
|
||||||
|
-- Dient als Basis fuer "Zuletzt gesehen"-Sortierung auf der Startseite.
|
||||||
|
CREATE TABLE recipe_view (
|
||||||
profile_id INTEGER NOT NULL REFERENCES profile(id) ON DELETE CASCADE,
|
profile_id INTEGER NOT NULL REFERENCES profile(id) ON DELETE CASCADE,
|
||||||
recipe_id INTEGER NOT NULL REFERENCES recipe(id) ON DELETE CASCADE,
|
recipe_id INTEGER NOT NULL REFERENCES recipe(id) ON DELETE CASCADE,
|
||||||
last_viewed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
last_viewed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (profile_id, recipe_id)
|
PRIMARY KEY (profile_id, recipe_id)
|
||||||
);
|
);
|
||||||
CREATE INDEX idx_recipe_views_recent
|
CREATE INDEX idx_recipe_view_recent
|
||||||
ON recipe_views (profile_id, last_viewed_at DESC);
|
ON recipe_view (profile_id, last_viewed_at DESC);
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { describe, it, expect } from 'vitest';
|
|||||||
import { openInMemoryForTest } from '../../src/lib/server/db';
|
import { openInMemoryForTest } from '../../src/lib/server/db';
|
||||||
|
|
||||||
describe('014_recipe_views migration', () => {
|
describe('014_recipe_views migration', () => {
|
||||||
it('creates recipe_views table with expected columns', () => {
|
it('creates recipe_view table with expected columns', () => {
|
||||||
const db = openInMemoryForTest();
|
const db = openInMemoryForTest();
|
||||||
const cols = db.prepare("PRAGMA table_info(recipe_views)").all() as Array<{
|
const cols = db.prepare("PRAGMA table_info(recipe_view)").all() as Array<{
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
notnull: number;
|
notnull: number;
|
||||||
@@ -15,16 +15,17 @@ describe('014_recipe_views migration', () => {
|
|||||||
expect(byName.profile_id?.notnull).toBe(1);
|
expect(byName.profile_id?.notnull).toBe(1);
|
||||||
expect(byName.profile_id?.pk).toBe(1);
|
expect(byName.profile_id?.pk).toBe(1);
|
||||||
expect(byName.recipe_id?.type).toBe('INTEGER');
|
expect(byName.recipe_id?.type).toBe('INTEGER');
|
||||||
|
expect(byName.recipe_id?.notnull).toBe(1);
|
||||||
expect(byName.recipe_id?.pk).toBe(2);
|
expect(byName.recipe_id?.pk).toBe(2);
|
||||||
expect(byName.last_viewed_at?.type).toBe('TEXT');
|
expect(byName.last_viewed_at?.type).toBe('TIMESTAMP');
|
||||||
expect(byName.last_viewed_at?.notnull).toBe(1);
|
expect(byName.last_viewed_at?.notnull).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has index on (profile_id, last_viewed_at DESC)', () => {
|
it('has index on (profile_id, last_viewed_at DESC)', () => {
|
||||||
const db = openInMemoryForTest();
|
const db = openInMemoryForTest();
|
||||||
const idxList = db
|
const idxList = db
|
||||||
.prepare("PRAGMA index_list(recipe_views)")
|
.prepare("PRAGMA index_list(recipe_view)")
|
||||||
.all() as Array<{ name: string }>;
|
.all() as Array<{ name: string }>;
|
||||||
expect(idxList.some((i) => i.name === 'idx_recipe_views_recent')).toBe(true);
|
expect(idxList.some((i) => i.name === 'idx_recipe_view_recent')).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user