diff --git a/library/Icinga/Data/Db/DbQuery.php b/library/Icinga/Data/Db/DbQuery.php index c50049ee7..94765d98f 100644 --- a/library/Icinga/Data/Db/DbQuery.php +++ b/library/Icinga/Data/Db/DbQuery.php @@ -96,14 +96,14 @@ class DbQuery extends SimpleQuery public function getSelectQuery() { $select = $this->dbSelect(); - // Add order fields to select for postgres distinct queries (#6351) if ($this->hasOrder() && $this->getDatasource()->getDbType() === 'pgsql' && $select->getPart(Zend_Db_Select::DISTINCT) === true) { foreach ($this->getOrder() as $fieldAndDirection) { - list($alias, $field) = explode('.', $fieldAndDirection[0]); - $this->columns[$field] = $fieldAndDirection[0]; + if (array_search($fieldAndDirection[0], $this->columns) === false) { + $this->columns[] = $fieldAndDirection[0]; + } } } @@ -264,6 +264,7 @@ class DbQuery extends SimpleQuery $this->applyFilterSql($count); if ($this->useSubqueryCount) { + $count->columns($this->columns); $columns = array('cnt' => 'COUNT(*)'); return $this->db->select()->from($count, $columns); } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php index ec79ef63c..ab1947f7e 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php @@ -79,7 +79,7 @@ class GroupSummaryQuery extends IdoQuery } $union = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL); - $this->select->from(array('statussummary' => $union), array($groupColumn))->group(array($groupColumn)); + $this->select->from(array('statussummary' => $union), array())->group(array($groupColumn)); $this->joinedVirtualTables = array( 'servicestatussummary' => true, diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index d3aca9934..e390aa114 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -8,6 +8,29 @@ use Zend_Db_Expr; class StatusQuery extends IdoQuery { + /** + * This mode represents whether we are in HostStatus or ServiceStatus + * + * Implemented for `distinct as workaround + * + * @TODO Subject to change, see #7344 + * + * @var string + */ + protected $mode; + + /** + * Sets the mode of the current query + * + * @TODO Subject to change, see #7344 + * + * @param string $mode + */ + public function setMode($mode) + { + $this->mode = $mode; + } + protected $allowCustomVars = true; protected $columnMap = array( @@ -430,6 +453,12 @@ class StatusQuery extends IdoQuery array() ); + // @TODO Subject to change, see #7344 + if ($this->mode === 'host' || $this->mode === 'service') { + $this->useSubqueryCount = true; + $this->distinct(); + } + return $this; } @@ -449,7 +478,11 @@ class StatusQuery extends IdoQuery . ' AND hgo.is_active = 1', array() ); - + // @TODO Subject to change, see #7344 + if ($this->mode === 'service') { + $this->distinct(); + $this->useSubqueryCount = true; + } return $this; } @@ -471,6 +504,14 @@ class StatusQuery extends IdoQuery array() ); + // @TODO Subject to change, see #7344 + if ($this->mode === 'host' || $this->mode === 'service') { + $this->distinct(); + } + if ($this->mode === 'host') { + $this->useSubqueryCount = true; + } + return $this; } diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index 661412c43..df331999e 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -7,7 +7,6 @@ namespace Icinga\Module\Monitoring\DataView; use Countable; use Icinga\Data\Filter\Filter; use Icinga\Data\Filter\FilterMatch; -use Icinga\Data\SimpleQuery; use Icinga\Data\Browsable; use Icinga\Data\PivotTable; use Icinga\Data\Sortable; @@ -26,9 +25,9 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable /** * The query used to populate the view * - * @var SimpleQuery + * @var \Icinga\Data\SimpleQuery */ - private $query; + protected $query; protected $filter; @@ -39,8 +38,8 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable /** * Create a new view * - * @param SimpleQuery $query Which backend to query - * @param array $columns Select columns + * @param ConnectionInterface $connection + * @param array $columns */ public function __construct(ConnectionInterface $connection, array $columns = null) { @@ -48,6 +47,18 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable $queryClass = $connection->getQueryClass($this->getQueryName()); $this->query = new $queryClass($this->connection->getResource(), $columns); $this->filter = Filter::matchAll(); + $this->init(); + } + + /** + * Initializer for `distinct purposes + * + * Implemented for `distinct as workaround + * + * @TODO Subject to change, see #7344 + */ + public function init() + { } /** @@ -64,17 +75,17 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable return $tableName; } -public function where($condition, $value = null) -{ - $this->filter->addFilter(Filter::where($condition, $value)); - $this->query->where($condition, $value); - return $this; -} + public function where($condition, $value = null) + { + $this->filter->addFilter(Filter::where($condition, $value)); + $this->query->where($condition, $value); + return $this; + } -public function dump() -{ - return $this->query->dump(); -} + public function dump() + { + return $this->query->dump(); + } /** * Retrieve columns provided by this view @@ -194,9 +205,10 @@ public function dump() * Sort the rows, according to the specified sort column and order * * @param string $column Sort column - * @param int $order Sort order, one of the SORT_ constants + * @param string $order Sort order, one of the SORT_ constants * - * @return self + * @return $this + * @throws QueryException If the sort column is not allowed * @see DataView::SORT_ASC * @see DataView::SORT_DESC * @deprecated Use DataView::order() instead @@ -204,42 +216,43 @@ public function dump() public function sort($column = null, $order = null) { $sortRules = $this->getSortRules(); - - if ($sortRules !== null) { - if ($column === null) { - $sortColumns = reset($sortRules); + if ($column === null) { + // Use first available sort rule as default + if (empty($sortRules)) { + return $this; + } + $sortColumns = reset($sortRules); + if (! isset($sortColumns['columns'])) { + $sortColumns['columns'] = array(key($sortRules)); + } + } else { + if (isset($sortRules[$column])) { + $sortColumns = $sortRules[$column]; if (! isset($sortColumns['columns'])) { - $sortColumns['columns'] = array(key($sortRules)); + $sortColumns['columns'] = array($column); } } else { - if (isset($sortRules[$column])) { - $sortColumns = $sortRules[$column]; - if (! isset($sortColumns['columns'])) { - $sortColumns['columns'] = array($column); - } - } else { - $sortColumns = array( - 'columns' => array($column), - 'order' => $order - ); - }; - } - - $order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : self::SORT_ASC) : $order; - $order = (strtoupper($order) === self::SORT_ASC) ? 'ASC' : 'DESC'; - - foreach ($sortColumns['columns'] as $column) { - if (! $this->isValidFilterTarget($column)) { - throw new QueryException( - t('The sort column "%s" is not allowed in "%s".'), - $column, - get_class($this) - ); - } - $this->query->order($column, $order); - } - $this->isSorted = true; + $sortColumns = array( + 'columns' => array($column), + 'order' => $order + ); + }; } + + $order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : static::SORT_ASC) : $order; + $order = (strtoupper($order) === static::SORT_ASC) ? 'ASC' : 'DESC'; + + foreach ($sortColumns['columns'] as $column) { + if (! $this->isValidFilterTarget($column)) { + throw new QueryException( + t('The sort column "%s" is not allowed in "%s".'), + $column, + get_class($this) + ); + } + $this->query->order($column, $order); + } + $this->isSorted = true; return $this; } @@ -250,7 +263,7 @@ public function dump() */ public function getSortRules() { - return null; + return array(); } /** @@ -259,7 +272,7 @@ public function dump() * @param string $column * @param string $direction * - * @return self + * @return $this */ public function order($column = null, $direction = null) { @@ -294,7 +307,7 @@ public function dump() /** * Return the query which was created in the constructor * - * @return mixed + * @return \Icinga\Data\SimpleQuery */ public function getQuery() { @@ -365,6 +378,9 @@ public function dump() */ public function paginate($itemsPerPage = null, $pageNumber = null) { + if (! $this->isSorted) { + $this->order(); + } return $this->query->paginate($itemsPerPage, $pageNumber); } diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php index ff2ecaf91..e9b5b60dd 100644 --- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php @@ -6,6 +6,14 @@ namespace Icinga\Module\Monitoring\DataView; class HostStatus extends DataView { + /** + * @see DataView::init() + */ + public function init() + { + $this->query->setMode('host'); + } + /** * Retrieve columns provided by this view * diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index 45cde745f..9edcabc87 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -6,6 +6,16 @@ namespace Icinga\Module\Monitoring\DataView; class ServiceStatus extends DataView { + /** + * Sets the mode for `distinct as workaround + * + * @TODO Subject to change, see #7344 + */ + public function init() + { + $this->query->setMode('service'); + } + /** * Retrieve columns provided by this view *