From 214a34a5a851924d53a69760bea602fe034f9346 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@icinga.com>
Date: Tue, 13 Aug 2019 17:16:58 +0200
Subject: [PATCH 1/3] Always use subquery filters for subquery targets in the
 group views

---
 .../Monitoring/Backend/Ido/Query/HostgroupQuery.php   | 11 ++---------
 .../Backend/Ido/Query/ServicegroupQuery.php           | 11 ++---------
 2 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
index 8b6b74435..15372ded2 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
@@ -3,8 +3,6 @@
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
-use Icinga\Exception\NotImplementedError;
-
 /**
  * Query for host groups
  */
@@ -276,13 +274,8 @@ class HostgroupQuery extends IdoQuery
     protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
     {
         if ($name === 'hostgroup') {
-            if (! $and) {
-                // IN AND NOT IN works for OR filters w/o subquery joins
-                throw new NotImplementedError('');
-            } else {
-                // Propagate that the "parent" query has to be filtered as well
-                $additionalFilter = clone $filter;
-            }
+            // Propagate that the "parent" query has to be filtered as well
+            $additionalFilter = clone $filter;
 
             $this->requireVirtualTable('members');
 
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
index d43c7d7a3..8ad3de7c7 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
@@ -3,8 +3,6 @@
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
-use Icinga\Exception\NotImplementedError;
-
 class ServicegroupQuery extends IdoQuery
 {
     protected $groupBase = array(
@@ -290,13 +288,8 @@ class ServicegroupQuery extends IdoQuery
 
             return ['so.object_id', 'so.object_id'];
         } elseif ($name === 'servicegroup') {
-            if (! $and) {
-                // IN AND NOT IN for OR filters works w/o subquery joins
-                throw new NotImplementedError('');
-            } else {
-                // Propagate that the "parent" query has to be filtered as well
-                $additionalFilter = clone $filter;
-            }
+            // Propagate that the "parent" query has to be filtered as well
+            $additionalFilter = clone $filter;
 
             $this->requireVirtualTable('members');
 

From c8ed889114c856c894a82b7c9ca388229d29f4a7 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@icinga.com>
Date: Tue, 13 Aug 2019 17:19:45 +0200
Subject: [PATCH 2/3] Fix operator in wildcard filter chains

---
 library/Icinga/Data/Db/DbQuery.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/library/Icinga/Data/Db/DbQuery.php b/library/Icinga/Data/Db/DbQuery.php
index 25de96742..fffd7b08a 100644
--- a/library/Icinga/Data/Db/DbQuery.php
+++ b/library/Icinga/Data/Db/DbQuery.php
@@ -312,17 +312,19 @@ class DbQuery extends SimpleQuery
                 if (! empty($comp)) {
                     $sql[] = $col . ' IN (' . $this->escapeForSql($comp) . ')';
                 }
+                $operator = 'OR';
             } elseif ($sign === '!=') {
                 if (! empty($comp)) {
                     $sql[] = sprintf('(%1$s NOT IN (%2$s) OR %1$s IS NULL)', $col, $this->escapeForSql($comp));
                 }
+                $operator = 'AND';
             } else {
                 throw new QueryException(
                     'Unable to render array expressions with operators other than equal or not equal'
                 );
             }
 
-            return '(' . implode(' OR ', $sql) . ')';
+            return '(' . implode(" $operator ", $sql) . ')';
         } elseif ($sign === '=' && strpos($expression, '*') !== false) {
             if ($expression === '*') {
                 return new Zend_Db_Expr('TRUE');

From fadf12e98a5f612f4475ea7c49d0eec46dffc7de Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@icinga.com>
Date: Wed, 14 Aug 2019 10:26:05 +0200
Subject: [PATCH 3/3] Show empty groups with a filter chain too

---
 .../library/Monitoring/Backend/Ido/Query/IdoQuery.php       | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
index 7a39f48d1..51df5e7b7 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
@@ -633,6 +633,12 @@ abstract class IdoQuery extends DbQuery
             new Zend_Db_Expr($ours)
         ));
 
+        if (! $negate) {
+            $subQueryFilter = $subQueryFilter->orFilter(
+                new FilterExpression($ours, '', new Zend_Db_Expr('IS NULL'))
+            );
+        }
+
         $subQuery
             ->setFilter($subQueryFilter)
             ->clearGroupingRules()