From 387a4dee0f0fd1eacce9852a079c25ffc0fb058d Mon Sep 17 00:00:00 2001 From: Nicolas Castellano Date: Sun, 16 Mar 2025 19:31:22 -0300 Subject: [PATCH 1/5] Added input parser option searchLeafNodes, used as an identifier for furthest children notes of the search query ONLY --- app/src/main/java/com/orgzly/android/query/Options.kt | 5 ++++- .../java/com/orgzly/android/query/user/DottedQueryParser.kt | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/orgzly/android/query/Options.kt b/app/src/main/java/com/orgzly/android/query/Options.kt index e2fc76f07..4728f4a8e 100644 --- a/app/src/main/java/com/orgzly/android/query/Options.kt +++ b/app/src/main/java/com/orgzly/android/query/Options.kt @@ -1,3 +1,6 @@ package com.orgzly.android.query -data class Options(val agendaDays: Int = 0) \ No newline at end of file +data class Options( + val agendaDays: Int = 0, + val searchLeafNodes: Boolean = false +) \ No newline at end of file diff --git a/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt b/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt index 874ee04ae..9b69f1b4e 100644 --- a/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt +++ b/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt @@ -113,6 +113,10 @@ open class DottedQueryParser : QueryParser() { OptionMatch("""^ad\.(\d+)$""") { match, options -> val days = match.groupValues[1].toInt() if (days > 0) options.copy(agendaDays = days) else null + }, + OptionMatch("""^(\.)?h\.(.+)""") { match, options -> + if (match.groupValues[2].lowercase() == HyerarchyType.LEAF.toString().lowercase()) + options.copy(searchLeafNodes = true) else null } ) } From 271b6fc8048c13b343b80dbcd8d64759cf6e2ca6 Mon Sep 17 00:00:00 2001 From: Nicolas Castellano Date: Mon, 17 Mar 2025 21:08:39 -0300 Subject: [PATCH 2/5] Added new CTE query that gets the child notes from an array of note ids long type formatted --- .../com/orgzly/android/data/DataRepository.kt | 27 +++++++++++++++++++ .../com/orgzly/android/db/dao/NoteViewDao.kt | 22 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/app/src/main/java/com/orgzly/android/data/DataRepository.kt b/app/src/main/java/com/orgzly/android/data/DataRepository.kt index d27570804..1faba05ec 100644 --- a/app/src/main/java/com/orgzly/android/data/DataRepository.kt +++ b/app/src/main/java/com/orgzly/android/data/DataRepository.kt @@ -9,6 +9,7 @@ import android.net.Uri import android.os.Handler import android.text.TextUtils import androidx.lifecycle.LiveData +import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations import androidx.localbroadcastmanager.content.LocalBroadcastManager @@ -1159,6 +1160,32 @@ class DataRepository @Inject constructor( val sqlQuery = buildSqlQuery(query) + if (query.options.searchLeafNodes) { // If search contained "h.leaf" in it, + // display only leaf nodes of the live data query + val result = MediatorLiveData>() + val parentNotesLiveData = db.noteView().runQueryLiveData(sqlQuery) + + result.addSource(parentNotesLiveData) { parentNotes -> + if (parentNotes.isNotEmpty()) { + var parentIds = parentNotes.map { it.note.id } + + val leafNotesLiveData = db.noteView().runQueryLeafNotesData(parentIds) // This is a recursive + // CTE (Common Table Expression) that searches all the child nodes of the parent ids, + // the returning result filters out the notes with ids that have children in the same selection + + result.removeSource(parentNotesLiveData) + + result.addSource(leafNotesLiveData) { leafNotes -> + result.value = leafNotes + } + } else { + result.value = emptyList() + } + } + + return result + } + return db.noteView().runQueryLiveData(sqlQuery) } diff --git a/app/src/main/java/com/orgzly/android/db/dao/NoteViewDao.kt b/app/src/main/java/com/orgzly/android/db/dao/NoteViewDao.kt index 19858d945..b974c68c8 100644 --- a/app/src/main/java/com/orgzly/android/db/dao/NoteViewDao.kt +++ b/app/src/main/java/com/orgzly/android/db/dao/NoteViewDao.kt @@ -26,6 +26,28 @@ abstract class NoteViewDao { """) abstract fun getVisibleLiveData(bookId: Long): LiveData> + @Query(""" + WITH RECURSIVE temp_notes AS ( + $QUERY + GROUP BY notes.id, event_timestamp + ), + rec_search_leaf_notes AS ( + select * from temp_notes + WHERE temp_notes.id IN (:noteIdList) + UNION ALL + SELECT + a.* + FROM temp_notes a + JOIN rec_search_leaf_notes b ON b.id = a.parent_id + ) + SELECT DISTINCT b.* + FROM rec_search_leaf_notes b + WHERE b.id NOT IN ( + SELECT parent_id FROM rec_search_leaf_notes WHERE parent_id IS NOT NULL + ) + """) + abstract fun runQueryLeafNotesData(noteIdList: List): LiveData> + @Query(""" $QUERY WHERE notes.book_id = :bookId From 6321dfd6a45977bc93dee3e355c9754c91dced0d Mon Sep 17 00:00:00 2001 From: Nicolas Castellano Date: Tue, 18 Mar 2025 15:08:57 -0300 Subject: [PATCH 3/5] Added HyerarchyType enum class --- app/src/main/java/com/orgzly/android/query/HyerarchyType.kt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 app/src/main/java/com/orgzly/android/query/HyerarchyType.kt diff --git a/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt b/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt new file mode 100644 index 000000000..7860d54a2 --- /dev/null +++ b/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt @@ -0,0 +1,3 @@ +package com.orgzly.android.query + +enum class HyerarchyType { LEAF } \ No newline at end of file From 03170e4ca9f6d2b8f2e170eac13452d15c8e3b9e Mon Sep 17 00:00:00 2001 From: Nicolas Castellano Date: Tue, 18 Mar 2025 15:17:41 -0300 Subject: [PATCH 4/5] Fixed typo HyerarchyType enum class name for HierarchyType --- app/src/main/java/com/orgzly/android/query/HyerarchyType.kt | 2 +- .../java/com/orgzly/android/query/user/DottedQueryParser.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt b/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt index 7860d54a2..00b134147 100644 --- a/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt +++ b/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt @@ -1,3 +1,3 @@ package com.orgzly.android.query -enum class HyerarchyType { LEAF } \ No newline at end of file +enum class HierarchyType { LEAF } \ No newline at end of file diff --git a/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt b/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt index 9b69f1b4e..a0dab9aae 100644 --- a/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt +++ b/app/src/main/java/com/orgzly/android/query/user/DottedQueryParser.kt @@ -115,7 +115,7 @@ open class DottedQueryParser : QueryParser() { if (days > 0) options.copy(agendaDays = days) else null }, OptionMatch("""^(\.)?h\.(.+)""") { match, options -> - if (match.groupValues[2].lowercase() == HyerarchyType.LEAF.toString().lowercase()) + if (match.groupValues[2].lowercase() == HierarchyType.LEAF.toString().lowercase()) options.copy(searchLeafNodes = true) else null } ) From 609101765ae235d1dead7c0787289845cb397d02 Mon Sep 17 00:00:00 2001 From: Nicolas Castellano Date: Tue, 18 Mar 2025 15:37:46 -0300 Subject: [PATCH 5/5] Renamed file containing the HierarchyType (previously called HyerarchyType) enum class to HierarchyType.kt --- .../orgzly/android/query/{HyerarchyType.kt => HierarchyType.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/orgzly/android/query/{HyerarchyType.kt => HierarchyType.kt} (100%) diff --git a/app/src/main/java/com/orgzly/android/query/HyerarchyType.kt b/app/src/main/java/com/orgzly/android/query/HierarchyType.kt similarity index 100% rename from app/src/main/java/com/orgzly/android/query/HyerarchyType.kt rename to app/src/main/java/com/orgzly/android/query/HierarchyType.kt