@@ -288,6 +288,89 @@ func TestSearchDiaryEntriesByEmbedding_LimitEdgeCases(t *testing.T) {
288288 })
289289}
290290
291+ func TestSetHNSWEfSearch (t * testing.T ) {
292+ db := testutil .SetupTestDB (t )
293+ ctx := context .Background ()
294+
295+ t .Run ("トランザクション内でhnsw.ef_searchを設定できる" , func (t * testing.T ) {
296+ tx , err := db .BeginTx (ctx , nil )
297+ if err != nil {
298+ t .Fatalf ("トランザクション開始失敗: %v" , err )
299+ }
300+ defer func () { _ = tx .Rollback () }()
301+
302+ if err := database .SetHNSWEfSearch (ctx , tx , 100 ); err != nil {
303+ t .Fatalf ("SetHNSWEfSearch失敗: %v" , err )
304+ }
305+ })
306+ }
307+
308+ func TestInsertSemanticSearchLog (t * testing.T ) {
309+ db := testutil .SetupTestDB (t )
310+ ctx := context .Background ()
311+ userID := testutil .CreateTestUser (t , db , "semantic-search-log@example.com" , "User" )
312+
313+ t .Run ("意味的検索ログを挿入できる" , func (t * testing.T ) {
314+ if err := database .InsertSemanticSearchLog (ctx , db , userID ); err != nil {
315+ t .Fatalf ("InsertSemanticSearchLog失敗: %v" , err )
316+ }
317+
318+ var count int
319+ if err := db .QueryRowContext (ctx , `SELECT COUNT(*) FROM semantic_search_logs WHERE user_id = $1` , userID ).Scan (& count ); err != nil {
320+ t .Fatalf ("カウントクエリ失敗: %v" , err )
321+ }
322+ if count != 1 {
323+ t .Errorf ("期待 1, 実際 %d" , count )
324+ }
325+ })
326+ }
327+
328+ func TestDiaryIDsWithoutEmbeddings (t * testing.T ) {
329+ db := testutil .SetupTestDB (t )
330+ ctx := context .Background ()
331+ userID := testutil .CreateTestUser (t , db , "diary-ids-without-embeddings@example.com" , "User" )
332+
333+ diaryID := uuid .New ()
334+ now := time .Now ().UnixMilli ()
335+ if _ , err := db .ExecContext (ctx ,
336+ `INSERT INTO diaries (id, user_id, content, date, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6)` ,
337+ diaryID , userID , "embedding未生成の日記" , "2024-01-01" , now , now ,
338+ ); err != nil {
339+ t .Fatalf ("日記の挿入に失敗: %v" , err )
340+ }
341+
342+ t .Run ("embedding未生成の日記IDを返す" , func (t * testing.T ) {
343+ ids , err := database .DiaryIDsWithoutEmbeddings (ctx , db , userID )
344+ if err != nil {
345+ t .Fatalf ("DiaryIDsWithoutEmbeddings失敗: %v" , err )
346+ }
347+ if len (ids ) != 1 {
348+ t .Errorf ("期待 1件, 実際 %d件" , len (ids ))
349+ }
350+ if len (ids ) > 0 && ids [0 ] != diaryID .String () {
351+ t .Errorf ("期待ID %s, 実際 %s" , diaryID , ids [0 ])
352+ }
353+ })
354+
355+ t .Run ("embedding生成済みの日記は含まない" , func (t * testing.T ) {
356+ dummyEmbedding := make ([]float32 , 3072 )
357+ chunks := []database.DiaryChunk {
358+ {Index : 0 , Content : "テスト" , Summary : "テスト概要" , Embedding : dummyEmbedding },
359+ }
360+ if err := database .UpsertDiaryChunkEmbeddings (ctx , db , diaryID , userID , chunks , "gemini-embedding-001" ); err != nil {
361+ t .Fatalf ("UpsertDiaryChunkEmbeddings失敗: %v" , err )
362+ }
363+
364+ ids , err := database .DiaryIDsWithoutEmbeddings (ctx , db , userID )
365+ if err != nil {
366+ t .Fatalf ("DiaryIDsWithoutEmbeddings失敗: %v" , err )
367+ }
368+ if len (ids ) != 0 {
369+ t .Errorf ("embedding生成済みで0件を期待したが %d件" , len (ids ))
370+ }
371+ })
372+ }
373+
291374func TestUpsertDiaryChunkEmbeddings_NonSQLDB (t * testing.T ) {
292375 // db が *sql.DB でない場合にエラーが返ることを確認
293376 // NOTE: 現在の実装では *sql.DB 以外は受け付けないが、
0 commit comments