From b8efe314a00581c0c4f6c92c5e6d65d52ec84d5f Mon Sep 17 00:00:00 2001
From: Johannes Meyer <johannes.meyer@netways.de>
Date: Mon, 15 Jun 2015 13:59:46 +0200
Subject: [PATCH] DbQuery: Ignore wildcard only filters

This increases query performance vastly, since LIKE '%' comparisons
prevent the dbms from utilizing an index.
---
 library/Icinga/Data/Db/DbQuery.php                | 15 +++++++++++++++
 .../Monitoring/Backend/Ido/Query/IdoQuery.php     |  8 ++++++++
 2 files changed, 23 insertions(+)

diff --git a/library/Icinga/Data/Db/DbQuery.php b/library/Icinga/Data/Db/DbQuery.php
index a151babf7..2f82b06b2 100644
--- a/library/Icinga/Data/Db/DbQuery.php
+++ b/library/Icinga/Data/Db/DbQuery.php
@@ -285,12 +285,27 @@ class DbQuery extends SimpleQuery
         if ($this->isTimestamp($col)) {
             $expression = $this->valueToTimestamp($expression);
         }
+
         if (is_array($expression) && $sign === '=') {
             // TODO: Should we support this? Doesn't work for blub*
             return $col . ' IN (' . $this->escapeForSql($expression) . ')';
         } elseif ($sign === '=' && strpos($expression, '*') !== false) {
+            if ($expression === '*') {
+                // We'll ignore such filters as it prevents index usage and because "*" means anything, anything means
+                // all whereas all means that whether we use a filter to match anything or no filter at all makes no
+                // difference, except for performance reasons...
+                return '';
+            }
+
             return $col . ' LIKE ' . $this->escapeForSql($this->escapeWildcards($expression));
         } elseif ($sign === '!=' && strpos($expression, '*') !== false) {
+            if ($expression === '*') {
+                // We'll ignore such filters as it prevents index usage and because "*" means nothing, so whether we're
+                // using a real column with a valid comparison here or just an expression which cannot be evaluated to
+                // true makes no difference, except for performance reasons...
+                return $this->escapeForSql(0);
+            }
+
             return $col . ' NOT LIKE ' . $this->escapeForSql($this->escapeWildcards($expression));
         } else {
             return $col . ' ' . $sign . ' ' . $this->escapeForSql($expression);
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
index 1feff0f71..6d0f418da 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
@@ -267,6 +267,10 @@ abstract class IdoQuery extends DbQuery
     protected function requireFilterColumns(Filter $filter)
     {
         if ($filter instanceof FilterExpression) {
+            if ($filter->getExpression() === '*') {
+                return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
+            }
+
             $col = $filter->getColumn();
             $this->requireColumn($col);
 
@@ -328,6 +332,10 @@ abstract class IdoQuery extends DbQuery
 
     public function where($condition, $value = null)
     {
+        if ($value === '*') {
+            return $this; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
+        }
+
         $this->requireColumn($condition);
         $col = $this->getMappedField($condition);
         if ($col === null) {