icingadb-web/library/Icingadb/Model/ServicegroupSummary.php
Eric Lippmann d0725fb45a PostgreSQL: Group summaries: Fix type resolution for UNION
Type resolution for UNION (CASE and related constructs) in PostgreSQL
works by taking the UNIONed queries 2 at a time, i.e. the first TWO
queries are resolved, then it takes the result and resolves it with the
next query and so on.

Previously, when using Hostgroup as the first query and Host (or
Service) as the next query, PostgreSQL encounters two NULL values for
the host_handled (or service_handled) column, resulting in the type
text. This leads to the following error:

UNION types text and boolenum cannot be matched.

Now Hostgroup is the last query that ensures there are not two
consecutive NULL values for host_handled (or service_handled).

NOTE: BREAKING: This change breaks other code that extracts the "base
query" which depends on Hostgroup or Servicegroup being the first query
in the getUnions() array, which has yet to be fixed.  In preparation for
a possible fix that could simply use the last query instead of the
first, the Servicegroup query has also been moved to the end.
2022-05-24 16:04:23 +02:00

118 lines
3.9 KiB
PHP

<?php
/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */
namespace Icinga\Module\Icingadb\Model;
use Icinga\Module\Icingadb\Model\Behavior\Binary;
use ipl\Orm\Behaviors;
use ipl\Orm\UnionModel;
use ipl\Sql\Expression;
class ServicegroupSummary extends UnionModel
{
public function getTableName()
{
return 'servicegroup';
}
public function getKeyName()
{
return ['id' => 'servicegroup_id'];
}
public function getColumns()
{
return [
'display_name' => 'servicegroup_display_name',
'name' => 'servicegroup_name',
'services_critical_handled' => new Expression(
'SUM(CASE WHEN service_state = 2 AND service_handled = \'y\' THEN 1 ELSE 0 END)'
),
'services_critical_unhandled' => new Expression(
'SUM(CASE WHEN service_state = 2 AND service_handled = \'n\' THEN 1 ELSE 0 END)'
),
'services_ok' => new Expression(
'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)'
),
'services_pending' => new Expression(
'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)'
),
'services_total' => new Expression(
'SUM(CASE WHEN service_id IS NOT NULL THEN 1 ELSE 0 END)'
),
'services_unknown_handled' => new Expression(
'SUM(CASE WHEN service_state = 3 AND service_handled = \'y\' THEN 1 ELSE 0 END)'
),
'services_unknown_unhandled' => new Expression(
'SUM(CASE WHEN service_state = 3 AND service_handled = \'n\' THEN 1 ELSE 0 END)'
),
'services_warning_handled' => new Expression(
'SUM(CASE WHEN service_state = 1 AND service_handled = \'y\' THEN 1 ELSE 0 END)'
),
'services_warning_unhandled' => new Expression(
'SUM(CASE WHEN service_state = 1 AND service_handled = \'n\' THEN 1 ELSE 0 END)'
),
'services_severity' => new Expression('MAX(service_severity)')
];
}
public function getAggregateColumns()
{
return true;
}
public function getSearchColumns()
{
return ['display_name'];
}
public function getDefaultSort()
{
return 'display_name';
}
public function getUnions()
{
$unions = [
[
Service::class,
[
'servicegroup',
'state'
],
[
'servicegroup_id' => 'servicegroup.id',
'servicegroup_name' => new Expression('NULL'),
'servicegroup_display_name' => new Expression('NULL'),
'service_id' => 'service.id',
'service_state' => 'state.soft_state',
'service_handled' => 'state.is_handled',
'service_severity' => 'state.severity'
]
],
[
Servicegroup::class,
[],
[
'servicegroup_id' => 'servicegroup.id',
'servicegroup_name' => 'servicegroup.name',
'servicegroup_display_name' => 'servicegroup.display_name',
'service_id' => new Expression('NULL'),
'service_state' => new Expression('NULL'),
'service_handled' => new Expression('NULL'),
'service_severity' => new Expression('0')
]
]
];
return $unions;
}
public function createBehaviors(Behaviors $behaviors)
{
$behaviors->add(new Binary([
'id'
]));
}
}