Merge pull request #3457 from Icinga/feature/proper-results-when-filtering-for-linked-objects-2934

Proper results when filtering for linked objects
This commit is contained in:
Johannes Meyer 2018-07-19 09:15:58 +02:00 committed by GitHub
commit dab9fea0d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 640 additions and 5 deletions

View File

@ -23,6 +23,11 @@ class ContactgroupQuery extends IdoQuery
*/
protected $groupOrigin = array('hosts', 'members', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -187,4 +192,23 @@ class ContactgroupQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$this->requireVirtualTable('hosts');
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$this->requireVirtualTable('services');
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class HostcommentQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -179,4 +184,19 @@ class HostcommentQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class HostcommenthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -171,4 +176,19 @@ class HostcommenthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -17,6 +17,11 @@ class HostcontactQuery extends IdoQuery
protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
protected $subQueryTargets = [
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
];
protected $columnMap = [
'contactgroups' => [
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
@ -189,6 +194,8 @@ class HostcontactQuery extends IdoQuery
*/
protected function joinServices()
{
$this->joinHosts();
$this->select->joinLeft(
['s' => $this->prefix . 'services'],
's.host_object_id = ho.object_id',
@ -216,4 +223,23 @@ class HostcontactQuery extends IdoQuery
[]
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$this->requireVirtualTable('hosts');
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$this->requireVirtualTable('services');
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class HostdowntimeQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -185,4 +190,19 @@ class HostdowntimeQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class HostdowntimestarthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -180,4 +185,19 @@ class HostdowntimestarthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class HostflappingstarthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -170,4 +175,19 @@ class HostflappingstarthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -3,6 +3,8 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Exception\NotImplementedError;
/**
* Query for host groups
*/
@ -18,6 +20,11 @@ class HostgroupQuery extends IdoQuery
protected $groupOrigin = array('members');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
protected $columnMap = array(
'hostgroups' => array(
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
@ -223,4 +230,31 @@ class HostgroupQuery extends IdoQuery
array()
);
}
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;
}
$this->requireVirtualTable('members');
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$this->requireVirtualTable('members');
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -13,6 +13,11 @@ class HostnotificationQuery extends IdoQuery
*/
protected $allowCustomVars = true;
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -232,4 +237,19 @@ class HostnotificationQuery extends IdoQuery
return $group;
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -33,6 +33,11 @@ class HoststatehistoryQuery extends IdoQuery
'hard_state' => 1
);
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -186,4 +191,19 @@ class HoststatehistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -20,6 +20,11 @@ class HoststatusQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -292,4 +297,19 @@ class HoststatusQuery extends IdoQuery
'unhandled_service_count'
));
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 'ho.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('services');
return ['s.host_object_id', 'ho.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -11,6 +11,7 @@ use Icinga\Data\Db\DbQuery;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotImplementedError;
use Icinga\Exception\ProgrammingError;
use Icinga\Exception\QueryException;
use Icinga\Web\Session;
@ -149,6 +150,13 @@ abstract class IdoQuery extends DbQuery
*/
protected $groupOrigin = array();
/**
* Map of table names to query names for which to create subquery filters
*
* @var array
*/
protected $subQueryTargets = array();
/**
* The primary key column for the instances table
*
@ -492,6 +500,160 @@ abstract class IdoQuery extends DbQuery
return $this;
}
/**
* Prepare the given query so that it can be linked to the parent
*
* @param IdoQuery $query
* @param string $name
* @param FilterExpression $filter The filter which initiated the sub query
* @param bool $and Whether it's an AND filter
* @param bool $negate Whether it's an != filter
* @param FilterExpression $additionalFilter Filters which should be applied to the "parent" query
*
* @return array The first value is their, the second our key column
*
* @throws NotImplementedError In case the given query is unknown
*/
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
throw new NotImplementedError('Query "%s" is unknown', $name);
}
/**
* Create and return a sub-query filter for the given filter expression
*
* @param FilterExpression $filter
* @param string $queryName
*
* @return Filter
*
* @throws QueryException
*/
protected function createSubQueryFilter(FilterExpression $filter, $queryName)
{
$expr = $filter->getExpression();
$op = $filter->getSign();
if ($op === '=' && ! is_array($expr) && $op !== '!=') {
// We're joining a subquery only if the filter is enclosed in parentheses or if it's a != filter,
// e.g. hostgroup_name=(linux...), hostgroup_name!=linux, hostgroup_name!=(linux...)
throw new NotImplementedError('');
}
$subQuery = $this->createSubQuery($queryName);
$subQuery->setIsSubQuery();
$subQueryFilter = clone $filter;
if ($op === '!=') {
$negate = true;
if (! is_array($expr)) {
// We assume that expression is an array later on but we'll support subquery joins for != filters
// which are not enclosed in parentheses
$expr = [$expr];
}
} else {
$negate = false;
}
if (count($expr) === 1 && strpos($expr[0], '&') !== false) {
// Our current filter implementation does not specify & as a control character so the count of the
// expression array is always one in this case
$expr = explode('&', $expr[0]);
$subQueryFilter->setExpression($expr);
$and = true;
} else {
// Or filters are respected by our filter implementation. No special handling needed here
$and = false;
}
$additional = null;
list($theirs, $ours) = $this->joinSubQuery($subQuery, $queryName, $subQueryFilter, $and, $negate, $additional);
$zendSelect = $subQuery->select();
$fromPart = $zendSelect->getPart($zendSelect::FROM);
$zendSelect->reset($zendSelect::FROM);
foreach ($fromPart as $correlationName => $joinOptions) {
if (isset($joinOptions['joinCondition'])) {
$joinOptions['joinCondition'] = preg_replace(
'/(?<=^|\s)\w+(?=\.)/',
'sub_$0',
$joinOptions['joinCondition']
);
}
$name = ['sub_' . $correlationName => $joinOptions['tableName']];
switch ($joinOptions['joinType']) {
case $zendSelect::FROM:
$zendSelect->from($name);
break;
case $zendSelect::INNER_JOIN:
$zendSelect->joinInner($name, $joinOptions['joinCondition'], null);
break;
case $zendSelect::LEFT_JOIN:
$zendSelect->joinLeft($name, $joinOptions['joinCondition'], null);
break;
default:
// TODO: Add support for other join types if required?
throw new QueryException(
'Unsupported join type %s. Cannot create subquery filter.',
$joinOptions['joinType']
);
}
}
if ($and || $negate && ! $and) {
// Having is only required for AND and != filters,
// e.g. hostgroup_name=(ping&linux), hostgroup_name!=ping, hostgroup_name!=(ping|linux)
$groups = $subQuery->getGroup();
$group = $groups[0];
$group = preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $group);
$cnt = count($expr);
$subQuery->select()->having("COUNT(DISTINCT $group) >= $cnt");
}
$subQueryFilter->setColumn(preg_replace(
'/(?<=^|\s)\w+(?=\.)/',
'sub_$0',
$subQuery->aliasToColumnName($filter->getColumn())
));
if ($negate) {
// != will be NOT EXISTS later
$subQueryFilter = $subQueryFilter->setSign('=');
}
$subQueryFilter = $subQueryFilter->andFilter(Filter::where(
preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $theirs),
new Zend_Db_Expr($ours)
));
$subQuery
->setFilter($subQueryFilter)
->clearGroupingRules()
->select()
->reset('columns')
->columns([new Zend_Db_Expr('1')]);
// EXISTS is the column name because without any column $this->isCustomVar() fails badly otherwise.
// Additionally it bypasses the non-required optimizations made by our filter rendering implementation.
$exists = new FilterExpression($negate ? 'NOT EXISTS' : 'EXISTS', '', new Zend_Db_Expr($subQuery));
if ($additional !== null) {
$alias = $additional->getColumn();
$this->requireColumn($alias);
$additional->setColumn($this->aliasToColumnName($alias));
return Filter::matchAll($exists, $additional);
}
return $exists;
}
protected function requireFilterColumns(Filter $filter)
{
if ($filter instanceof FilterExpression) {
@ -500,6 +662,16 @@ abstract class IdoQuery extends DbQuery
}
$alias = $filter->getColumn();
$virtualTable = $this->aliasToTableName($alias);
if (isset($this->subQueryTargets[$virtualTable])) {
try {
return $this->createSubQueryFilter($filter, $this->subQueryTargets[$virtualTable]);
} catch (NotImplementedError $e) {
// We don't want to create subquery filters in all cases
}
}
$this->requireColumn($alias);
if ($this->isCustomvar($alias)) {
@ -519,8 +691,12 @@ abstract class IdoQuery extends DbQuery
$filter->setColumn($column);
} else {
foreach ($filter->filters() as $filter) {
$this->requireFilterColumns($filter);
foreach ($filter->filters() as $child) {
$replacement = $this->requireFilterColumns($child);
if ($replacement !== null) {
// setId($child->getId()) is performed because replaceById() doesn't already do it
$filter->replaceById($child->getId(), $replacement->setId($child->getId()));
}
}
}
}
@ -531,8 +707,7 @@ abstract class IdoQuery extends DbQuery
public function addFilter(Filter $filter)
{
$filter = clone $filter;
$this->requireFilterColumns($filter);
return parent::addFilter($filter);
return parent::addFilter($this->requireFilterColumns($filter) ?: $filter);
}
public function where($condition, $value = null)

View File

@ -23,6 +23,11 @@ class ServicecommentQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -193,4 +198,21 @@ class ServicecommentQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$this->requireVirtualTable('services');
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 's.host_object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class ServicecommenthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -169,4 +174,19 @@ class ServicecommenthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('services');
return ['so.object_id', 'so.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -17,6 +17,11 @@ class ServicecontactQuery extends IdoQuery
protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
protected $subQueryTargets = [
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
];
protected $columnMap = [
'contactgroups' => [
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
@ -212,4 +217,19 @@ class ServicecontactQuery extends IdoQuery
[]
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 's.host_object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class ServicedowntimeQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -199,4 +204,19 @@ class ServicedowntimeQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('services');
return ['so.object_id', 'so.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class ServicedowntimestarthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -178,4 +183,19 @@ class ServicedowntimestarthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('services');
return ['so.object_id', 'so.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class ServiceflappingstarthistoryQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -169,4 +174,19 @@ class ServiceflappingstarthistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('services');
return ['so.object_id', 'so.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -3,10 +3,12 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Exception\NotImplementedError;
class ServicegroupQuery extends IdoQuery
{
protected $groupBase = array(
'servicegroups' => array('sgo.object_id, sg.servicegroup_id'),
'servicegroups' => array('sgo.object_id', 'sg.servicegroup_id'),
'servicestatus' => array('ss.servicestatus_id', 'hs.hoststatus_id')
);
@ -14,6 +16,11 @@ class ServicegroupQuery extends IdoQuery
protected $allowCustomVars = true;
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
protected $columnMap = array(
'hostgroups' => array(
'hostgroup_name' => 'hgo.name1'
@ -178,4 +185,29 @@ class ServicegroupQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$this->requireVirtualTable('members');
$query->joinVirtualTable('services');
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;
}
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -13,6 +13,11 @@ class ServicenotificationQuery extends IdoQuery
*/
protected $allowCustomVars = true;
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -233,4 +238,21 @@ class ServicenotificationQuery extends IdoQuery
return $group;
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$this->requireVirtualTable('services');
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 's.host_object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -33,6 +33,11 @@ class ServicestatehistoryQuery extends IdoQuery
'hard_state' => 1
);
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -184,4 +189,19 @@ class ServicestatehistoryQuery extends IdoQuery
array()
);
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('services');
return ['so.object_id', 'so.object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}

View File

@ -23,6 +23,11 @@ class ServicestatusQuery extends IdoQuery
*/
protected $groupOrigin = array('hostgroups', 'servicegroups');
protected $subQueryTargets = array(
'hostgroups' => 'hostgroup',
'servicegroups' => 'servicegroup'
);
/**
* {@inheritdoc}
*/
@ -413,4 +418,19 @@ class ServicestatusQuery extends IdoQuery
parent::registerGroupColumns($alias, $table, $groupedColumns, $groupedTables);
}
}
protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
{
if ($name === 'hostgroup') {
$query->joinVirtualTable('members');
return ['hgm.host_object_id', 's.host_object_id'];
} elseif ($name === 'servicegroup') {
$query->joinVirtualTable('members');
return ['sgm.service_object_id', 'so.object_id'];
}
return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
}
}