From 22437d005a3f59a9abc6e6e251a5188f36a7f3c5 Mon Sep 17 00:00:00 2001 From: Adrien Morais Date: Mon, 27 Sep 2021 15:36:28 +0200 Subject: [PATCH 1/2] enh(resource-status): escape "_" character to use indexed search --- .../Monitoring/Resource/Provider/MetaServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php index 3d42ce3a26f..16c8e60318a 100644 --- a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php +++ b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php @@ -156,7 +156,7 @@ private function prepareSubQuery( FROM `:dbstg`.`services` AS s INNER JOIN `:dbstg`.`hosts` sh ON sh.host_id = s.host_id - AND sh.name LIKE '_Module_Meta%' + AND sh.name LIKE '\_Module\_Meta%' AND sh.enabled = 1"; // set ACL limitations From f15cded4fe6f9c37ea998657a518ece0cb674258 Mon Sep 17 00:00:00 2001 From: Adrien Morais Date: Tue, 12 Oct 2021 21:38:52 +0200 Subject: [PATCH 2/2] enh(resources): use EXISTS statement instead of INNER JOIN --- .../Resource/Provider/HostProvider.php | 19 +++--- .../Resource/Provider/MetaServiceProvider.php | 20 ++++--- .../Resource/Provider/ServiceProvider.php | 54 +++++++++-------- .../Resource/ResourceRepositoryRDB.php | 58 ++++++++++++------- 4 files changed, 87 insertions(+), 64 deletions(-) diff --git a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/HostProvider.php b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/HostProvider.php index 6c7a3a02870..49fe4686edb 100644 --- a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/HostProvider.php +++ b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/HostProvider.php @@ -69,9 +69,9 @@ public function prepareSubQueryWithAcl( StatementCollector $collector, array $accessGroupIds ): string { - $aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS host_acl ON host_acl.host_id = h.host_id + $aclSubQuery = ' EXISTS (SELECT 1 FROM `:dbstg`.`centreon_acl` AS host_acl WHERE host_acl.host_id = h.host_id AND host_acl.service_id IS NULL - AND host_acl.group_id IN (' . implode(',', $accessGroupIds) . ') '; + AND host_acl.group_id IN (' . implode(',', $accessGroupIds) . ') LIMIT 1) '; return $this->prepareSubQuery($filter, $collector, $aclSubQuery); } @@ -89,7 +89,7 @@ private function prepareSubQuery( StatementCollector $collector, ?string $aclSubQuery ): string { - $sql = "SELECT DISTINCT + $sql = "SELECT h.host_id AS `id`, 'host' AS `type`, h.name AS `name`, @@ -164,11 +164,6 @@ private function prepareSubQuery( AND host_cvl.service_id = 0 AND host_cvl.name = "CRITICALITY_LEVEL"'; - // set ACL limitations - if ($aclSubQuery !== null) { - $sql .= $aclSubQuery; - } - $hasWhereCondition = false; $this->sqlRequestTranslator->setConcordanceArray($this->hostConcordances); @@ -183,9 +178,15 @@ private function prepareSubQuery( $sql .= $searchRequest; } + // set ACL limitations + if ($aclSubQuery !== null) { + $sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ') . $aclSubQuery; + $hasWhereCondition = true; + } + // show active hosts and aren't related to some module $sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ') - . 'h.enabled = 1 AND h.name NOT LIKE "_Module_%"'; + . 'h.enabled = 1 AND h.name NOT LIKE "\_Module\_%"'; // apply the state filter to SQL query if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) { diff --git a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php index 16c8e60318a..ad9f5bfdb92 100644 --- a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php +++ b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/MetaServiceProvider.php @@ -69,9 +69,12 @@ public function prepareSubQueryWithAcl( StatementCollector $collector, array $accessGroupIds ): string { - $aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS service_acl ON service_acl.host_id = s.host_id - AND service_acl.service_id = s.service_id - AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') '; + $aclSubQuery = ' EXISTS ( + SELECT 1 FROM `:dbstg`.`centreon_acl` AS service_acl + WHERE service_acl.host_id = s.host_id + AND service_acl.service_id = s.service_id + AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') + LIMIT 1) '; return $this->prepareSubQuery($filter, $collector, $aclSubQuery); } @@ -89,7 +92,7 @@ private function prepareSubQuery( StatementCollector $collector, ?string $aclSubQuery ): string { - $sql = "SELECT DISTINCT + $sql = "SELECT SUBSTRING(s.description, 6) AS `id`, 'metaservice' AS `type`, s.display_name AS `name`, @@ -159,14 +162,15 @@ private function prepareSubQuery( AND sh.name LIKE '\_Module\_Meta%' AND sh.enabled = 1"; + // show active services only + $sql .= ' WHERE s.enabled = 1 '; + + // set ACL limitations if ($aclSubQuery !== null) { - $sql .= $aclSubQuery; + $sql .= ' AND ' . $aclSubQuery; } - // show active services only - $sql .= ' WHERE s.enabled = 1'; - // apply the state filter to SQL query if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) { $sqlState = []; diff --git a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/ServiceProvider.php b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/ServiceProvider.php index e31c53e1182..2ae1b52ccb8 100644 --- a/src/Centreon/Infrastructure/Monitoring/Resource/Provider/ServiceProvider.php +++ b/src/Centreon/Infrastructure/Monitoring/Resource/Provider/ServiceProvider.php @@ -71,9 +71,12 @@ public function prepareSubQueryWithAcl( StatementCollector $collector, array $accessGroupIds ): string { - $aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS service_acl ON service_acl.host_id = s.host_id - AND service_acl.service_id = s.service_id - AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') '; + $aclSubQuery = ' EXISTS ( + SELECT 1 FROM `:dbstg`.`centreon_acl` AS service_acl + WHERE service_acl.host_id = s.host_id + AND service_acl.service_id = s.service_id + AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') + LIMIT 1) '; return $this->prepareSubQuery($filter, $collector, $aclSubQuery); } @@ -182,28 +185,6 @@ private function prepareSubQuery( AND service_cvl.service_id = s.service_id AND service_cvl.name = "CRITICALITY_LEVEL"'; - // set ACL limitations - if ($aclSubQuery !== null) { - $sql .= $aclSubQuery; - } - - // apply the service group filter to SQL query - if ($filter->getServicegroupNames()) { - $groupList = []; - - foreach ($filter->getServicegroupNames() as $index => $groupName) { - $key = ":serviceServicegroupName_{$index}"; - - $groupList[] = $key; - $collector->addValue($key, $groupName, \PDO::PARAM_STR); - } - - $sql .= ' INNER JOIN `:dbstg`.`services_servicegroups` AS ssg - ON ssg.host_id = s.host_id AND ssg.service_id = s.service_id - INNER JOIN `:dbstg`.`servicegroups` AS sg - ON ssg.servicegroup_id = sg.servicegroup_id AND sg.name IN (' . implode(', ', $groupList) . ') '; - } - $hasWhereCondition = false; $this->sqlRequestTranslator->setConcordanceArray($this->serviceConcordances); @@ -222,6 +203,29 @@ private function prepareSubQuery( $sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ') . 's.enabled = 1'; + // set ACL limitations + if ($aclSubQuery !== null) { + $sql .= ' AND ' . $aclSubQuery; + } + + // apply the service group filter to SQL query + if ($filter->getServicegroupNames()) { + $groupList = []; + + foreach ($filter->getServicegroupNames() as $index => $groupName) { + $key = ":serviceServicegroupName_{$index}"; + + $groupList[] = $key; + $collector->addValue($key, $groupName, \PDO::PARAM_STR); + } + + $sql .= ' AND EXISTS (SELECT 1 FROM `:dbstg`.`services_servicegroups` AS ssg + WHERE ssg.host_id = s.host_id AND ssg.service_id = s.service_id + AND EXISTS (SELECT 1 FROM `:dbstg`.`servicegroups` AS sg + WHERE ssg.servicegroup_id = sg.servicegroup_id + AND sg.id = ssg.id AND sg.name IN (' . implode(', ', $groupList) . ') LIMIT 1) LIMIT 1)'; + } + // apply the state filter to SQL query if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) { $sqlState = []; diff --git a/src/Centreon/Infrastructure/Monitoring/Resource/ResourceRepositoryRDB.php b/src/Centreon/Infrastructure/Monitoring/Resource/ResourceRepositoryRDB.php index 06b263de944..e0fc4870eed 100644 --- a/src/Centreon/Infrastructure/Monitoring/Resource/ResourceRepositoryRDB.php +++ b/src/Centreon/Infrastructure/Monitoring/Resource/ResourceRepositoryRDB.php @@ -68,7 +68,7 @@ final class ResourceRepositoryRDB extends AbstractRepositoryDRB implements Resou private $accessGroups = []; /** - * @var array Association of resource search parameters + * @var array Association of resource search parameters */ private $resourceConcordances = [ 'id' => 'resource.id', @@ -162,7 +162,7 @@ public function findResources(ResourceFilter $filter): array } $collector = new StatementCollector(); - $request = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT ' + $request = 'SELECT SQL_CALC_FOUND_ROWS ' . 'resource.id, resource.type, resource.name, resource.alias, resource.fqdn, ' . 'resource.host_id, resource.service_id, ' . 'resource.status_code, resource.status_name, resource.status_severity_code, ' // status @@ -211,11 +211,26 @@ function ($accessGroup) { return []; } - $request .= implode('UNION ALL ', $subRequests); + $request .= implode(' UNION ALL ', $subRequests); unset($subRequests); $request .= ') AS `resource`'; + $hasWhereCondition = false; + + // Search + $this->sqlRequestTranslator->setConcordanceArray($this->resourceConcordances); + try { + $searchRequest = $this->sqlRequestTranslator->translateSearchParameterToSql(); + } catch (RequestParametersTranslatorException $ex) { + throw new RepositoryException($ex->getMessage(), 0, $ex); + } + + if ($searchRequest !== null) { + $hasWhereCondition = true; + $request .= $searchRequest; + } + // apply the host group filter to SQL query if ($filter->getHostgroupNames()) { $groupList = []; @@ -226,10 +241,17 @@ function ($accessGroup) { $collector->addValue($key, $groupName, \PDO::PARAM_STR); } - $request .= ' INNER JOIN `:dbstg`.`hosts_hostgroups` AS hhg - ON hhg.host_id = resource.host_id - INNER JOIN `:dbstg`.`hostgroups` AS hg - ON hg.name IN (' . implode(', ', $groupList) . ') '; + $request .= ($hasWhereCondition === false) ? ' WHERE ' : ' AND '; + $hasWhereCondition = true; + + $request .= ' EXISTS ( + SELECT 1 FROM `:dbstg`.`hosts_hostgroups` AS hhg + WHERE hhg.host_id = resource.host_id + AND EXISTS ( + SELECT 1 FROM `:dbstg`.`hostgroups` AS hg + WHERE hg.hostgroup_id = hhg.hostgroup_id AND hg.name IN (' . implode(', ', $groupList) . ') + LIMIT 1) + LIMIT 1) '; } /** @@ -237,25 +259,17 @@ function ($accessGroup) { * Then only resources with existing metrics referencing index_data services will be returned. */ if ($filter->getOnlyWithPerformanceData() === true) { - $request .= ' INNER JOIN `:dbstg`.index_data AS idata - ON idata.host_id = resource.parent_id + $request .= $hasWhereCondition ? ' AND ' : ' WHERE '; + $request .= ' EXISTS ( + SELECT 1 FROM `:dbstg`.index_data AS idata + WHERE idata.host_id = resource.parent_id AND idata.service_id = resource.id AND resource.type = "service" - INNER JOIN `:dbstg`.metrics AS m - ON m.index_id = idata.id - AND m.hidden = "0" '; - } - - // Search - $this->sqlRequestTranslator->setConcordanceArray($this->resourceConcordances); - try { - $searchRequest = $this->sqlRequestTranslator->translateSearchParameterToSql(); - } catch (RequestParametersTranslatorException $ex) { - throw new RepositoryException($ex->getMessage(), 0, $ex); + AND EXISTS (SELECT 1 FROM `:dbstg`.metrics AS m + WHERE m.index_id = idata.id + AND m.hidden = "0" LIMIT 1) LIMIT 1) '; } - $request .= $searchRequest !== null ? $searchRequest : ''; - foreach ($this->sqlRequestTranslator->getSearchValues() as $key => $data) { $collector->addValue($key, current($data), key($data)); }