diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index 5c0cbba82..91b8e4ca0 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -485,22 +485,16 @@ abstract class IdoQuery extends DbQuery if ($filter->getExpression() === '*') { return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing } + $alias = $filter->getColumn(); $this->requireColumn($alias); + if ($this->isCustomvar($alias)) { $column = $this->getCustomvarColumnName($alias); } else { $column = $this->aliasToColumnName($alias); } - if (isset($this->columnsWithoutCollation[$alias])) { - $expression = $filter->getExpression(); - if (is_array($expression)) { - $filter->setExpression(array_map('strtolower', $expression)); - } else { - $filter->setExpression(strtolower($expression)); - } - } $filter->setColumn($column); } else { foreach ($filter->filters() as $filter) { @@ -519,11 +513,48 @@ abstract class IdoQuery extends DbQuery return parent::addFilter($filter); } + /** + * Recurse the given filter and ensure that any string conversion is case-insensitive + * + * @param Filter $filter + */ + protected function lowerColumnsWithoutCollation(Filter $filter) + { + if ($filter instanceof FilterExpression) { + if ( + in_array($filter->getColumn(), $this->columnsWithoutCollation) + && strpos($filter->getColumn(), 'LOWER') !== 0 + ) { + $filter->setColumn('LOWER(' . $filter->getColumn() . ')'); + $expression = $filter->getExpression(); + if (is_array($expression)) { + $filter->setExpression(array_map('strtolower', $expression)); + } else { + $filter->setExpression(strtolower($expression)); + } + } + } else { + foreach ($filter->filters() as $chainedFilter) { + $this->lowerColumnsWithoutCollation($chainedFilter); + } + } + } + + protected function applyFilterSql($select) + { + if (! empty($this->columnsWithoutCollation)) { + $this->lowerColumnsWithoutCollation($this->filter); + } + + parent::applyFilterSql($select); + } + 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) { @@ -571,6 +602,7 @@ abstract class IdoQuery extends DbQuery if (! empty($this->columnsWithoutCollation)) { return in_array($column, $this->columnsWithoutCollation) || strpos($column, 'LOWER') !== 0; } + return preg_match('/ COLLATE .+$/', $column) === 1; } @@ -601,11 +633,11 @@ abstract class IdoQuery extends DbQuery { $this->customVarsJoinTemplate = '%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s'; - foreach ($this->columnMap as $table => &$columns) { - foreach ($columns as $alias => &$column) { - if (false !== $pos = strpos($column, ' COLLATE')) { - $column = 'LOWER(' . substr($column, 0, $pos) . ')'; - $this->columnsWithoutCollation[$alias] = true; + foreach ($this->columnMap as $table => & $columns) { + foreach ($columns as $alias => & $column) { + $column = preg_replace('/ COLLATE .+$/', '', $column, -1, $count); + if ($count > 0) { + $this->columnsWithoutCollation[] = $this->getMappedField($alias); } $column = preg_replace( '/inet_aton\(([[:word:].]+)\)/i',