From 31274d17a542173490e0359ebd86b6a2c394486a Mon Sep 17 00:00:00 2001 From: nkanaev Date: Mon, 11 May 2026 10:27:50 +0100 Subject: [PATCH] use nullable for field updates --- src/server/routes.go | 7 ++++--- src/server/routes_test.go | 2 +- src/storage/feed.go | 22 ++++++++++------------ src/storage/feed_test.go | 8 +++----- src/storage/storage.go | 9 +++++++++ src/worker/worker.go | 2 +- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/server/routes.go b/src/server/routes.go index 9f4b7c0..f78feb8 100644 --- a/src/server/routes.go +++ b/src/server/routes.go @@ -292,10 +292,11 @@ func (s *Server) handleFeed(c *router.Context) { } } if f_id, ok := body["folder_id"]; ok { - params.UpdateFolderID = true - if reflect.TypeOf(f_id).Kind() == reflect.Float64 { + if f_id == nil { + params.FolderID = storage.SetNullable[int64](nil) + } else if reflect.TypeOf(f_id).Kind() == reflect.Float64 { folderId := int64(f_id.(float64)) - params.FolderID = &folderId + params.FolderID = storage.SetNullable(&folderId) } } if link, ok := body["feed_link"]; ok { diff --git a/src/server/routes_test.go b/src/server/routes_test.go index ce2a5dc..61cdeee 100644 --- a/src/server/routes_test.go +++ b/src/server/routes_test.go @@ -80,7 +80,7 @@ func TestFeedIcons(t *testing.T) { db, _ := storage.New(":memory:") icon := []byte("test") feed := db.CreateFeed("", "", "", "", nil) - db.UpdateFeed(feed.Id, storage.UpdateFeedParams{Icon: &icon, UpdateIcon: true}) + db.UpdateFeed(feed.Id, storage.UpdateFeedParams{Icon: storage.SetNullable(&icon)}) log.SetOutput(os.Stderr) recorder := httptest.NewRecorder() diff --git a/src/storage/feed.go b/src/storage/feed.go index e1f555c..e086399 100644 --- a/src/storage/feed.go +++ b/src/storage/feed.go @@ -65,30 +65,28 @@ func (s *Storage) DeleteFeed(feedId int64) bool { } type UpdateFeedParams struct { - Title *string - FeedLink *string - FolderID *int64 - UpdateFolderID bool - Icon *[]byte - UpdateIcon bool + Title *string + FeedLink *string + FolderID Nullable[int64] + Icon Nullable[[]byte] } func (s *Storage) UpdateFeed(feedId int64, params UpdateFeedParams) (bool, error) { _, err := s.db.Exec(` update feeds set - title = coalesce(:title, title), + title = coalesce(:title, title), feed_link = coalesce(:feed_link, feed_link), folder_id = case when :update_folder_id then :folder_id else folder_id end, - icon = case when :update_icon then :icon else icon end + icon = case when :update_icon then :icon else icon end where id = :id `, sql.Named("id", feedId), sql.Named("title", params.Title), sql.Named("feed_link", params.FeedLink), - sql.Named("update_folder_id", params.UpdateFolderID), - sql.Named("folder_id", params.FolderID), - sql.Named("update_icon", params.UpdateIcon), - sql.Named("icon", params.Icon), + sql.Named("update_folder_id", params.FolderID.Set), + sql.Named("folder_id", params.FolderID.Value), + sql.Named("update_icon", params.Icon.Set), + sql.Named("icon", params.Icon.Value), ) if err != nil { log.Print(err) diff --git a/src/storage/feed_test.go b/src/storage/feed_test.go index 2e101e9..dbb46ff 100644 --- a/src/storage/feed_test.go +++ b/src/storage/feed_test.go @@ -56,11 +56,9 @@ func TestUpdateFeed(t *testing.T) { title := "newtitle" db.UpdateFeed(feed1.Id, UpdateFeedParams{ - Title: &title, - FolderID: &folder.Id, - UpdateFolderID: true, - Icon: &icon, - UpdateIcon: true, + Title: &title, + FolderID: SetNullable(&folder.Id), + Icon: SetNullable(&icon), }) feed2 := db.GetFeed(feed1.Id) diff --git a/src/storage/storage.go b/src/storage/storage.go index 28cccfb..b64e786 100644 --- a/src/storage/storage.go +++ b/src/storage/storage.go @@ -12,6 +12,15 @@ type Storage struct { db *sql.DB } +type Nullable[T any] struct { + Set bool + Value *T +} + +func SetNullable[T any](v *T) Nullable[T] { + return Nullable[T]{Set: true, Value: v} +} + func New(path string) (*Storage, error) { if pos := strings.IndexRune(path, '?'); pos == -1 { params := "_journal=WAL&_sync=NORMAL&_busy_timeout=5000&cache=shared" diff --git a/src/worker/worker.go b/src/worker/worker.go index 18a8d07..8fc8954 100644 --- a/src/worker/worker.go +++ b/src/worker/worker.go @@ -53,7 +53,7 @@ func (w *Worker) FindFeedFavicon(feed storage.Feed) { log.Printf("Failed to find favicon for %s (%s): %s", feed.FeedLink, feed.Link, err) } if icon != nil { - w.db.UpdateFeed(feed.Id, storage.UpdateFeedParams{Icon: icon, UpdateIcon: true}) + w.db.UpdateFeed(feed.Id, storage.UpdateFeedParams{Icon: storage.SetNullable(icon)}) } }