From e4e734f3dd6b47587d368c055648d42ecb71a1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Fri, 29 Jan 2021 20:40:06 +0100 Subject: [PATCH] Add --orphan filtering flag --- adapter/sqlite/note_dao.go | 5 +++++ adapter/sqlite/note_dao_test.go | 9 +++++++++ cmd/finder_opts.go | 5 +++++ core/note/find.go | 4 ++++ 4 files changed, 23 insertions(+) diff --git a/adapter/sqlite/note_dao.go b/adapter/sqlite/note_dao.go index 49e270a..8b2f4f9 100644 --- a/adapter/sqlite/note_dao.go +++ b/adapter/sqlite/note_dao.go @@ -410,6 +410,11 @@ func (d *NoteDAO) findRows(opts note.FinderOpts) (*sql.Rows, error) { whereExprs = append(whereExprs, expr) + case note.OrphanFilter: + whereExprs = append(whereExprs, `n.id NOT IN ( + SELECT target_id FROM links WHERE target_id IS NOT NULL + )`) + case note.DateFilter: value := "?" field := "n." + dateField(filter) diff --git a/adapter/sqlite/note_dao_test.go b/adapter/sqlite/note_dao_test.go index 53c249d..681bb16 100644 --- a/adapter/sqlite/note_dao_test.go +++ b/adapter/sqlite/note_dao_test.go @@ -527,6 +527,15 @@ func TestNoteDAOFindNotLinkingTo(t *testing.T) { ) } +func TestNoteDAOFindOrphan(t *testing.T) { + testNoteDAOFindPaths(t, + note.FinderOpts{ + Filters: []note.Filter{note.OrphanFilter{}}, + }, + []string{"ref/test/b.md", "f39c8.md", "log/2021-02-04.md", "index.md"}, + ) +} + func TestNoteDAOFindCreatedOn(t *testing.T) { testNoteDAOFindPaths(t, note.FinderOpts{ diff --git a/cmd/finder_opts.go b/cmd/finder_opts.go index cbda819..0f74231 100644 --- a/cmd/finder_opts.go +++ b/cmd/finder_opts.go @@ -23,6 +23,7 @@ type Filtering struct { LinkingTo []string `help:"Only the notes linking to the given notes" placeholder:"" short:"L"` NotLinkedBy []string `help:"Only the notes not linked by the given notes" placeholder:""` NotLinkingTo []string `help:"Only the notes not linking to the given notes" placeholder:""` + Orphan bool `help:"Only the notes which don't have any other note linking to them"` Exclude []string `help:"Excludes notes matching the given file path pattern from the list" short:"x" placeholder:""` Interactive bool `help:"Further filter the list of notes interactively" short:"i"` } @@ -154,6 +155,10 @@ func NewFinderOpts(zk *zk.Zk, filtering Filtering, sorting Sorting) (*note.Finde }) } + if filtering.Orphan { + filters = append(filters, note.OrphanFilter{}) + } + if filtering.Interactive { filters = append(filters, note.InteractiveFilter(true)) } diff --git a/core/note/find.go b/core/note/find.go index 8e7f65c..97e388d 100644 --- a/core/note/find.go +++ b/core/note/find.go @@ -52,6 +52,9 @@ type LinkingToFilter struct { Negate bool } +// OrphanFilter is a note filter used to select notes having no other notes linking to them. +type OrphanFilter struct{} + // DateFilter can be used to filter notes created or modified before, after or on a given date. type DateFilter struct { Date time.Time @@ -67,6 +70,7 @@ func (f PathFilter) sealed() {} func (f ExcludePathFilter) sealed() {} func (f LinkedByFilter) sealed() {} func (f LinkingToFilter) sealed() {} +func (f OrphanFilter) sealed() {} func (f DateFilter) sealed() {} func (f InteractiveFilter) sealed() {}