diff --git a/internal/models/note_test.go b/internal/models/note_test.go index 4be5053..dd9bbd6 100644 --- a/internal/models/note_test.go +++ b/internal/models/note_test.go @@ -95,38 +95,38 @@ func TestContentCompletionNoteValidation(t *testing.T) { func TestTitleLengthNoteValidation(t *testing.T) { testcases := []struct { - name string - title string - expectedError bool + name string + title string + expectedError bool }{ { - name: "Max valid title", - title: strings.Repeat("0", models.NoteTitleMaxLength), + name: "Max valid title", + title: strings.Repeat("0", models.NoteTitleMaxLength), expectedError: false, }, { - name: "Just over max valid title", - title: strings.Repeat("1", models.NoteTitleMaxLength + 1), + name: "Just over max valid title", + title: strings.Repeat("1", models.NoteTitleMaxLength+1), expectedError: true, }, { - name: "Double max valid title", - title: strings.Repeat("Bd", models.NoteTitleMaxLength), + name: "Double max valid title", + title: strings.Repeat("Bd", models.NoteTitleMaxLength), expectedError: true, }, { - name: "Random overmax valid title length", - title: strings.Repeat("1", models.NoteTitleMaxLength + rand.IntN(150)), + name: "Random overmax valid title length", + title: strings.Repeat("1", models.NoteTitleMaxLength+rand.IntN(150)), expectedError: true, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { note := models.Note{ - Title: tc.title, - Content: "Perfectly valid content " + tc.title, + Title: tc.title, + Content: "Perfectly valid content " + tc.title, LastUpdate: time.Now(), - ID: 1, + ID: 1, } err := note.Validate() @@ -143,4 +143,4 @@ func TestTitleLengthNoteValidation(t *testing.T) { fmt.Printf("Test case '%s' passed.\n", tc.name) }) } -} \ No newline at end of file +} diff --git a/internal/store/sqlite/sqlite.go b/internal/store/sqlite/sqlite.go index 635e5be..b9d414f 100644 --- a/internal/store/sqlite/sqlite.go +++ b/internal/store/sqlite/sqlite.go @@ -85,10 +85,14 @@ func (s *SQLiteStore) SaveNote(ctx context.Context, note models.Note) (models.No } defer tx.Rollback() + if err := note.Validate(); err != nil { + return models.Note{}, err + } + if note.ID == 0 { result, err := tx.ExecContext(ctx, ` - INSERT INTO notes (content, last_update) VALUES (?, ?); - `, note.Content, note.LastUpdate) + INSERT INTO notes (title, content, last_update) VALUES (?, ?, ?); + `, note.Title, note.Content, note.LastUpdate) if err != nil { return models.Note{}, fmt.Errorf("failed to insert note: %w", err) } @@ -99,14 +103,14 @@ func (s *SQLiteStore) SaveNote(ctx context.Context, note models.Note) (models.No note.ID = int(id) } else { _, err := s.scanNote(tx.QueryRowContext(ctx, ` - SELECT id, content, last_update FROM notes WHERE id = ?; + SELECT id, title, content, last_update FROM notes WHERE id = ?; `, note.ID)) if err != nil { return models.Note{}, fmt.Errorf("cannot update note not found: %w", err) } _, err = tx.ExecContext(ctx, ` - UPDATE notes SET content = ?, last_update = ? WHERE id = ?; - `, note.Content, note.LastUpdate, note.ID) + UPDATE notes SET title = ?, content = ?, last_update = ? WHERE id = ?; + `, note.Title, note.Content, note.LastUpdate, note.ID) if err != nil { return models.Note{}, fmt.Errorf("failed to update note: %w", err) } @@ -120,7 +124,7 @@ func (s *SQLiteStore) SaveNote(ctx context.Context, note models.Note) (models.No func (s *SQLiteStore) GetNoteByID(ctx context.Context, id int) (models.Note, error) { row := s.read.QueryRowContext(ctx, ` - SELECT id, content, last_update FROM notes WHERE id = ?; + SELECT id, title, content, last_update FROM notes WHERE id = ?; `, id) note, err := s.scanNote(row) if err != nil { @@ -134,7 +138,7 @@ func (s *SQLiteStore) GetNoteByID(ctx context.Context, id int) (models.Note, err func (s *SQLiteStore) GetAllNotes(ctx context.Context) ([]models.Note, error) { rows, err := s.read.QueryContext(ctx, ` - SELECT id, content, last_update FROM notes ORDER BY id ASC; + SELECT id, title, content, last_update FROM notes ORDER BY id ASC; `) if err != nil { return nil, fmt.Errorf("failed to query all notes: %w", err) @@ -177,8 +181,11 @@ func (s *SQLiteStore) validateSchema(ctx context.Context) error { CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, last_update TIMESTAMP NOT NULL, - content TEXT NOT NULL + title TEXT NOT NULL, + content BLOB NOT NULL ); + CREATE UNIQUE INDEX idx_id ON notes(id); + CREATE INDEX idx_title ON notes(title); `, nil) return err } @@ -193,7 +200,7 @@ func (s *SQLiteStore) getWriteTransaction(ctx context.Context) (*sql.Tx, error) func (s *SQLiteStore) scanNote(results scannable) (models.Note, error) { var note models.Note - err := results.Scan(¬e.ID, ¬e.Content, ¬e.LastUpdate) + err := results.Scan(¬e.ID, ¬e.Title, ¬e.Content, ¬e.LastUpdate) if err != nil { return models.Note{}, fmt.Errorf("failed to scan note: %w", err) } diff --git a/internal/store/sqlite/sqlite_test.go b/internal/store/sqlite/sqlite_test.go index fee3d1d..96d75a9 100644 --- a/internal/store/sqlite/sqlite_test.go +++ b/internal/store/sqlite/sqlite_test.go @@ -86,11 +86,13 @@ func TestSaveNote(t *testing.T) { name: "new note", note: models.Note{ Content: "Test note", + Title: "No Problem", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 1, Content: "Test note", + Title: "No Problem", LastUpdate: time.Now(), }, expectedError: false, @@ -98,11 +100,13 @@ func TestSaveNote(t *testing.T) { name: "new 2 note", note: models.Note{ Content: "Test note 2!", + Title: "No Problem", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 2, Content: "Test note 2!", + Title: "No Problem", LastUpdate: time.Now(), }, expectedError: false, @@ -112,11 +116,13 @@ func TestSaveNote(t *testing.T) { note: models.Note{ ID: 1, Content: "Updated note", + Title: "No Problem", LastUpdate: time.Now(), }, expectedNote: models.Note{ ID: 1, Content: "Updated note", + Title: "No Problem", LastUpdate: time.Now(), }, expectedError: false, @@ -126,6 +132,7 @@ func TestSaveNote(t *testing.T) { note: models.Note{ ID: 999, Content: "This note does not exist", + Title: "No Problem", LastUpdate: time.Now(), }, expectedNote: models.Note{}, @@ -168,6 +175,7 @@ func TestGetNoteByID(t *testing.T) { }() store.SaveNote(context.Background(), models.Note{ Content: "Test note", + Title: "Saved No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) @@ -183,6 +191,7 @@ func TestGetNoteByID(t *testing.T) { expectedNote: models.Note{ ID: 1, Content: "Test note", + Title: "Saved No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }, expectedError: false, @@ -259,10 +268,12 @@ func TestGetAllNotes(t *testing.T) { store.SaveNote(context.Background(), models.Note{ Content: "Test note 1", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 2", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC), }) @@ -277,11 +288,13 @@ func TestGetAllNotes(t *testing.T) { { ID: 1, Content: "Test note 1", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }, { ID: 2, Content: "Test note 2", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 2, 0, 0, 0, 0, time.UTC), }, }, @@ -324,14 +337,17 @@ func TestDeleteNoteByID(t *testing.T) { store.SaveNote(context.Background(), models.Note{ Content: "Test note 1", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 2", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), }) store.SaveNote(context.Background(), models.Note{ Content: "Test note 3", + Title: "No Problem", LastUpdate: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), })