From 4a305ac64b7fb9e64fc608c976e625dce4e7f76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=E2=89=A1ZRS?= <12814349+LZRS@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:30:17 +0300 Subject: [PATCH] Join filter queries using Intersect and Union --- .../google/android/fhir/search/MoreSearch.kt | 44 ++++++++++++------- .../android/fhir/search/NestedSearch.kt | 11 +++-- .../google/android/fhir/search/SearchTest.kt | 14 +++--- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/engine/src/main/java/com/google/android/fhir/search/MoreSearch.kt b/engine/src/main/java/com/google/android/fhir/search/MoreSearch.kt index e12919b8d7..fbba436943 100644 --- a/engine/src/main/java/com/google/android/fhir/search/MoreSearch.kt +++ b/engine/src/main/java/com/google/android/fhir/search/MoreSearch.kt @@ -365,19 +365,33 @@ internal fun Search.getQuery( var filterStatement = "" val filterArgs = mutableListOf() - val filterQuery = getFilterQueries() - filterQuery.forEachIndexed { i, it -> - filterStatement += - // spotless:off - """ - ${if (i == 0) "AND a.resourceUuid IN (" else "a.resourceUuid IN ("} - ${it.query} - ) - ${if (i != filterQuery.lastIndex) "${operation.logicalOperator} " else ""} - """.trimIndent() - // spotless:on - filterArgs.addAll(it.args) - } + val nestedSearchQuery = nestedSearches.nestedQuery(type, operation) + val filterQuery = + getFilterQueries().let { + if (nestedSearchQuery != null) { + it + nestedSearchQuery + } else { + it + } + } + val filterJoinOperator = + when (operation) { + Operation.OR -> "\nUNION\n" + Operation.AND -> "\nINTERSECT\n" + } + filterQuery + .takeIf { it.isNotEmpty() } + ?.let { + filterStatement += + it.joinToString( + separator = filterJoinOperator, + prefix = "AND a.resourceUuid IN (", + postfix = ")\n", + ) { fq -> + fq.query + } + filterArgs.addAll(it.flatMap { fq -> fq.args }) + } var limitStatement = "" val limitArgs = mutableListOf() @@ -390,10 +404,6 @@ internal fun Search.getQuery( } } - nestedSearches.nestedQuery(type, operation)?.let { - filterStatement += it.query - filterArgs.addAll(it.args) - } val whereArgs = mutableListOf() val nestedArgs = mutableListOf() val query = diff --git a/engine/src/main/java/com/google/android/fhir/search/NestedSearch.kt b/engine/src/main/java/com/google/android/fhir/search/NestedSearch.kt index 4818680ec5..962114377e 100644 --- a/engine/src/main/java/com/google/android/fhir/search/NestedSearch.kt +++ b/engine/src/main/java/com/google/android/fhir/search/NestedSearch.kt @@ -214,15 +214,20 @@ internal fun List.nestedQuery( return if (isEmpty()) { null } else { + val filterJoinOperator = + when (operation) { + Operation.OR -> "\nUNION\n" + Operation.AND -> "\nINTERSECT\n" + } + map { it.nestedQuery(type) } .let { searchQueries -> SearchQuery( query = searchQueries.joinToString( - prefix = "AND a.resourceUuid IN ", - separator = " ${operation.logicalOperator} a.resourceUuid IN", + separator = " $filterJoinOperator", ) { searchQuery -> - "(\n${searchQuery.query}\n) " + "\n${searchQuery.query}\n" }, args = searchQueries.flatMap { it.args }, ) diff --git a/engine/src/test/java/com/google/android/fhir/search/SearchTest.kt b/engine/src/test/java/com/google/android/fhir/search/SearchTest.kt index 6fea58fc2a..a208b59b59 100644 --- a/engine/src/test/java/com/google/android/fhir/search/SearchTest.kt +++ b/engine/src/test/java/com/google/android/fhir/search/SearchTest.kt @@ -1919,8 +1919,7 @@ class SearchTest { AND a.resourceUuid IN ( SELECT resourceUuid FROM StringIndexEntity WHERE resourceType = ? AND index_name = ? AND index_value = ? - ) - AND a.resourceUuid IN ( + INTERSECT SELECT resourceUuid FROM ResourceEntity a WHERE a.resourceType = ? AND a.resourceId IN ( @@ -1930,8 +1929,7 @@ class SearchTest { AND a.resourceUuid IN ( SELECT resourceUuid FROM TokenIndexEntity WHERE resourceType = ? AND index_name = ? AND (index_value = ? AND IFNULL(index_system,'') = ?) - ) - AND a.resourceUuid IN ( + INTERSECT SELECT resourceUuid FROM TokenIndexEntity WHERE resourceType = ? AND index_name = ? AND (index_value = ? AND IFNULL(index_system,'') = ?) ) @@ -2001,7 +1999,7 @@ class SearchTest { WHERE resourceType = ? AND index_name = ? AND (index_value = ? AND IFNULL(index_system,'') = ?) ) ) - ) AND a.resourceUuid IN( + INTERSECT SELECT resourceUuid FROM ResourceEntity a WHERE a.resourceType = ? AND a.resourceId IN ( @@ -2156,8 +2154,7 @@ class SearchTest { AND a.resourceUuid IN ( SELECT resourceUuid FROM StringIndexEntity WHERE resourceType = ? AND index_name = ? AND index_value = ? - ) - OR a.resourceUuid IN ( + UNION SELECT resourceUuid FROM StringIndexEntity WHERE resourceType = ? AND index_name = ? AND index_value = ? ) @@ -2189,8 +2186,7 @@ class SearchTest { AND a.resourceUuid IN ( SELECT resourceUuid FROM StringIndexEntity WHERE resourceType = ? AND index_name = ? AND index_value LIKE ? || '%' COLLATE NOCASE - ) - AND a.resourceUuid IN ( + INTERSECT SELECT resourceUuid FROM StringIndexEntity WHERE resourceType = ? AND index_name = ? AND (index_value LIKE ? || '%' COLLATE NOCASE OR index_value LIKE ? || '%' COLLATE NOCASE) )