feat(db): recipe_views table mit Profil-FK und Recent-Index
Tracking-Tabelle fuer Sort-Option Zuletzt angesehen. Composite-PK (profile_id, recipe_id) erlaubt INSERT OR REPLACE per Default-Timestamp. Index nach profile_id + last_viewed_at DESC fuer Sort-Query. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
8
src/lib/server/db/migrations/014_recipe_views.sql
Normal file
8
src/lib/server/db/migrations/014_recipe_views.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
CREATE TABLE recipe_views (
|
||||
profile_id INTEGER NOT NULL REFERENCES profile(id) ON DELETE CASCADE,
|
||||
recipe_id INTEGER NOT NULL REFERENCES recipe(id) ON DELETE CASCADE,
|
||||
last_viewed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (profile_id, recipe_id)
|
||||
);
|
||||
CREATE INDEX idx_recipe_views_recent
|
||||
ON recipe_views (profile_id, last_viewed_at DESC);
|
||||
30
tests/integration/recipe-views.test.ts
Normal file
30
tests/integration/recipe-views.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { openInMemoryForTest } from '../../src/lib/server/db';
|
||||
|
||||
describe('014_recipe_views migration', () => {
|
||||
it('creates recipe_views table with expected columns', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const cols = db.prepare("PRAGMA table_info(recipe_views)").all() as Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
notnull: number;
|
||||
pk: number;
|
||||
}>;
|
||||
const byName = Object.fromEntries(cols.map((c) => [c.name, c]));
|
||||
expect(byName.profile_id?.type).toBe('INTEGER');
|
||||
expect(byName.profile_id?.notnull).toBe(1);
|
||||
expect(byName.profile_id?.pk).toBe(1);
|
||||
expect(byName.recipe_id?.type).toBe('INTEGER');
|
||||
expect(byName.recipe_id?.pk).toBe(2);
|
||||
expect(byName.last_viewed_at?.type).toBe('TEXT');
|
||||
expect(byName.last_viewed_at?.notnull).toBe(1);
|
||||
});
|
||||
|
||||
it('has index on (profile_id, last_viewed_at DESC)', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const idxList = db
|
||||
.prepare("PRAGMA index_list(recipe_views)")
|
||||
.all() as Array<{ name: string }>;
|
||||
expect(idxList.some((i) => i.name === 'idx_recipe_views_recent')).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user