diff --git frontends/php/include/classes/api/CApiService.php frontends/php/include/classes/api/CApiService.php index bfb15c1f77..c18b8da352 100644 --- frontends/php/include/classes/api/CApiService.php +++ frontends/php/include/classes/api/CApiService.php @@ -373,7 +373,7 @@ class CApiService { protected function createSelectQuery($tableName, array $options) { $sqlParts = $this->createSelectQueryParts($tableName, $this->tableAlias(), $options); - return $this->createSelectQueryFromParts($sqlParts); + return self::createSelectQueryFromParts($sqlParts); } /** @@ -410,6 +410,31 @@ class CApiService { return $sqlParts; } + /** + * Returns DISTINCT modifier for sql statements with multiple joins. + * + * @param array $sql_parts An SQL parts array. + * + * @return string + */ + private static function dbDistinct(array $sql_parts) { + $count = count($sql_parts['from']); + + if ($count == 1 && array_key_exists('left_join', $sql_parts)) { + foreach ($sql_parts['left_join'] as $left_join) { + $r_table = DB::getSchema($left_join['table']); + + // Increase count when table linked by non-unique column. + if ($left_join['using'] !== $r_table['key']) { + $count++; + break; + } + } + } + + return ($count > 1 ? ' DISTINCT' : ''); + } + /** * Creates a SELECT SQL query from the given SQL parts array. * @@ -417,17 +442,21 @@ class CApiService { * * @return string The resulting SQL query */ - protected function createSelectQueryFromParts(array $sqlParts) { + protected static function createSelectQueryFromParts(array $sqlParts) { $sql_left_join = ''; if (array_key_exists('left_join', $sqlParts)) { - foreach ($sqlParts['left_join'] as $join) { - $sql_left_join .= ' LEFT JOIN '.$join['from'].' ON '.$join['on']; + $l_table = DB::getSchema($sqlParts['left_table']['table']); + + foreach ($sqlParts['left_join'] as $left_join) { + $sql_left_join .= ' LEFT JOIN '.$left_join['table'].' '.$left_join['alias']. + ' ON '.$sqlParts['left_table']['alias'].'.'.$l_table['key']. + '='.$left_join['alias'].'.'.$left_join['using']; } // Moving a left table to the end. - $left_table = $sqlParts['from'][$sqlParts['left_table']]; - unset($sqlParts['from'][$sqlParts['left_table']]); - $sqlParts['from'][$sqlParts['left_table']] = $left_table; + $table_id = $sqlParts['left_table']['table'].' '.$sqlParts['left_table']['alias']; + unset($sqlParts['from'][array_search($table_id, $sqlParts['from'])]); + $sqlParts['from'][] = $table_id; } $sqlSelect = implode(',', array_unique($sqlParts['select'])); @@ -436,7 +465,7 @@ class CApiService { $sqlGroup = empty($sqlParts['group']) ? '' : ' GROUP BY '.implode(',', array_unique($sqlParts['group'])); $sqlOrder = empty($sqlParts['order']) ? '' : ' ORDER BY '.implode(',', array_unique($sqlParts['order'])); - return 'SELECT'.zbx_db_distinct($sqlParts).' '.$sqlSelect. + return 'SELECT'.self::dbDistinct($sqlParts).' '.$sqlSelect. ' FROM '.$sqlFrom. $sql_left_join. $sqlWhere. diff --git frontends/php/include/classes/api/services/CAction.php frontends/php/include/classes/api/services/CAction.php index 46d91010d7..0e0d7cb662 100644 --- frontends/php/include/classes/api/services/CAction.php +++ frontends/php/include/classes/api/services/CAction.php @@ -327,7 +327,7 @@ class CAction extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($action = DBfetch($dbRes)) { if ($options['countOutput']) { $result = $action['rowscount']; diff --git frontends/php/include/classes/api/services/CAlert.php frontends/php/include/classes/api/services/CAlert.php index 43f09c83e2..2bbddd3121 100644 --- frontends/php/include/classes/api/services/CAlert.php +++ frontends/php/include/classes/api/services/CAlert.php @@ -322,7 +322,7 @@ class CAlert extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($alert = DBfetch($dbRes)) { if ($options['countOutput']) { $result = $alert['rowscount']; diff --git frontends/php/include/classes/api/services/CApplication.php frontends/php/include/classes/api/services/CApplication.php index 84b07db154..b3c15e44a4 100644 --- frontends/php/include/classes/api/services/CApplication.php +++ frontends/php/include/classes/api/services/CApplication.php @@ -201,7 +201,7 @@ class CApplication extends CApiService { // output $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($application = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CDCheck.php frontends/php/include/classes/api/services/CDCheck.php index 06ca6c181d..7b8cd46c59 100644 --- frontends/php/include/classes/api/services/CDCheck.php +++ frontends/php/include/classes/api/services/CDCheck.php @@ -121,7 +121,7 @@ class CDCheck extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($dcheck = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CDHost.php frontends/php/include/classes/api/services/CDHost.php index 4f65ed64bf..e4362af514 100644 --- frontends/php/include/classes/api/services/CDHost.php +++ frontends/php/include/classes/api/services/CDHost.php @@ -144,7 +144,7 @@ class CDHost extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($dhost = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CDRule.php frontends/php/include/classes/api/services/CDRule.php index d945e8f750..d8fd226786 100644 --- frontends/php/include/classes/api/services/CDRule.php +++ frontends/php/include/classes/api/services/CDRule.php @@ -139,7 +139,7 @@ class CDRule extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($drule = DBfetch($dbRes)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CDService.php frontends/php/include/classes/api/services/CDService.php index 78d57a0c4e..4425652e38 100644 --- frontends/php/include/classes/api/services/CDService.php +++ frontends/php/include/classes/api/services/CDService.php @@ -160,7 +160,7 @@ class CDService extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($dservice = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CDashboard.php frontends/php/include/classes/api/services/CDashboard.php index e4bd8cade8..bb8e1db9a4 100644 --- frontends/php/include/classes/api/services/CDashboard.php +++ frontends/php/include/classes/api/services/CDashboard.php @@ -129,7 +129,7 @@ class CDashboard extends CApiService { $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); $sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); - $result = DBselect($this->createSelectQueryFromParts($sql_parts), $options['limit']); + $result = DBselect(self::createSelectQueryFromParts($sql_parts), $options['limit']); while ($row = DBfetch($result)) { if ($options['countOutput']) { diff --git frontends/php/include/classes/api/services/CDiscoveryRule.php frontends/php/include/classes/api/services/CDiscoveryRule.php index 7f72b711b1..b559378654 100644 --- frontends/php/include/classes/api/services/CDiscoveryRule.php +++ frontends/php/include/classes/api/services/CDiscoveryRule.php @@ -248,7 +248,7 @@ class CDiscoveryRule extends CItemGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($item = DBfetch($res)) { if (!$options['countOutput']) { $result[$item['itemid']] = $item; @@ -2009,8 +2009,8 @@ class CDiscoveryRule extends CItemGeneral { || $this->outputIsRequested('error', $options['output']) || (is_array($options['search']) && array_key_exists('error', $options['search'])) || (is_array($options['filter']) && array_key_exists('state', $options['filter']))) { - $sqlParts['left_join']['item_rtdata'] = ['from' => 'item_rtdata ir', 'on' => 'ir.itemid=i.itemid']; - $sqlParts['left_table'] = $tableName; + $sqlParts['left_join'][] = ['alias' => 'ir', 'table' => 'item_rtdata', 'using' => 'itemid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } if (!$options['countOutput']) { diff --git frontends/php/include/classes/api/services/CEvent.php frontends/php/include/classes/api/services/CEvent.php index 2e531ba111..6c4b0b1d99 100644 --- frontends/php/include/classes/api/services/CEvent.php +++ frontends/php/include/classes/api/services/CEvent.php @@ -475,7 +475,7 @@ class CEvent extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($event = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { @@ -868,31 +868,26 @@ class CEvent extends CApiService { $sqlParts = parent::applyQueryOutputOptions($tableName, $tableAlias, $options, $sqlParts); if (!$options['countOutput']) { + // Select fields from event_recovery table using LEFT JOIN. if ($this->outputIsRequested('r_eventid', $options['output'])) { - // Select fields from event_recovery table using LEFT JOIN. - $sqlParts['select']['r_eventid'] = 'er1.r_eventid'; - $sqlParts['left_join'][] = ['from' => 'event_recovery er1', 'on' => 'er1.eventid=e.eventid']; - $sqlParts['left_table'] = 'e'; + $sqlParts['left_join'][] = ['alias' => 'er1', 'table' => 'event_recovery', 'using' => 'eventid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } - if ($this->outputIsRequested('c_eventid', $options['output']) - || $this->outputIsRequested('correlationid', $options['output']) - || $this->outputIsRequested('userid', $options['output'])) { - // Select fields from event_recovery table using LEFT JOIN. + // Select fields from event_recovery table using LEFT JOIN. + $left_join = false; - if ($this->outputIsRequested('c_eventid', $options['output'])) { - $sqlParts['select']['c_eventid'] = 'er2.c_eventid'; - } - if ($this->outputIsRequested('correlationid', $options['output'])) { - $sqlParts['select']['correlationid'] = 'er2.correlationid'; - } - if ($this->outputIsRequested('userid', $options['output'])) { - $sqlParts['select']['userid'] = 'er2.userid'; + foreach (['c_eventid', 'correlationid', 'userid'] as $field) { + if ($this->outputIsRequested($field, $options['output'])) { + $sqlParts['select'][$field] = 'er2.'.$field; + $left_join = true; } + } - $sqlParts['left_join'][] = ['from' => 'event_recovery er2', 'on' => 'er2.r_eventid=e.eventid']; - $sqlParts['left_table'] = 'e'; + if ($left_join) { + $sqlParts['left_join'][] = ['alias' => 'er2', 'table' => 'event_recovery', 'using' => 'r_eventid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } if ($options['selectRelatedObject'] !== null || $options['selectHosts'] !== null) { @@ -1029,7 +1024,7 @@ class CEvent extends CApiService { ]); $sqlParts['order'][] = 'a.clock DESC'; - $acknowledges = DBFetchArrayAssoc(DBselect($this->createSelectQueryFromParts($sqlParts)), 'acknowledgeid'); + $acknowledges = DBFetchArrayAssoc(DBselect(self::createSelectQueryFromParts($sqlParts)), 'acknowledgeid'); // if the user data is requested via extended output or specified fields, join the users table $userFields = ['alias', 'name', 'surname']; diff --git frontends/php/include/classes/api/services/CGraph.php frontends/php/include/classes/api/services/CGraph.php index b37099d639..44b00a3a1a 100644 --- frontends/php/include/classes/api/services/CGraph.php +++ frontends/php/include/classes/api/services/CGraph.php @@ -287,7 +287,7 @@ class CGraph extends CGraphGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($graph = DBfetch($dbRes)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CGraphItem.php frontends/php/include/classes/api/services/CGraphItem.php index 9e8e92e90e..75f4591ff0 100644 --- frontends/php/include/classes/api/services/CGraphItem.php +++ frontends/php/include/classes/api/services/CGraphItem.php @@ -109,7 +109,7 @@ class CGraphItem extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($gitem = DBfetch($dbRes)) { if ($options['countOutput']) { $result = $gitem['rowscount']; diff --git frontends/php/include/classes/api/services/CGraphPrototype.php frontends/php/include/classes/api/services/CGraphPrototype.php index 1931788e5e..24187a29e9 100644 --- frontends/php/include/classes/api/services/CGraphPrototype.php +++ frontends/php/include/classes/api/services/CGraphPrototype.php @@ -293,7 +293,7 @@ class CGraphPrototype extends CGraphGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($graph = DBfetch($dbRes)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CHistory.php frontends/php/include/classes/api/services/CHistory.php index a9ec4754b7..9d8a403612 100644 --- frontends/php/include/classes/api/services/CHistory.php +++ frontends/php/include/classes/api/services/CHistory.php @@ -222,7 +222,7 @@ class CHistory extends CApiService { $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); $sql_parts = $this->applyQuerySortOptions($this->tableName, $this->tableAlias(), $options, $sql_parts); - $db_res = DBselect($this->createSelectQueryFromParts($sql_parts), $options['limit']); + $db_res = DBselect(self::createSelectQueryFromParts($sql_parts), $options['limit']); while ($data = DBfetch($db_res)) { if ($options['countOutput']) { diff --git frontends/php/include/classes/api/services/CHost.php frontends/php/include/classes/api/services/CHost.php index e26795fdd7..b7945b2670 100644 --- frontends/php/include/classes/api/services/CHost.php +++ frontends/php/include/classes/api/services/CHost.php @@ -467,7 +467,7 @@ class CHost extends CHostGeneral { $sqlParts = $this->applyQueryFilterOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($host = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { @@ -534,11 +534,8 @@ class CHost extends CHostGeneral { if ((!$options['countOutput'] && $this->outputIsRequested('inventory_mode', $options['output'])) || ($options['filter'] && array_key_exists('inventory_mode', $options['filter']))) { - $sqlParts['left_join'][] = [ - 'from' => 'host_inventory hinv', - 'on' => $this->tableAlias().'.'.$this->pk().'=hinv.hostid' - ]; - $sqlParts['left_table'] = $this->tableName(); + $sqlParts['left_join'][] = ['alias' => 'hinv', 'table' => 'host_inventory', 'using' => 'hostid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } return $sqlParts; diff --git frontends/php/include/classes/api/services/CHostGroup.php frontends/php/include/classes/api/services/CHostGroup.php index 25a4ada7b5..f251aace01 100644 --- frontends/php/include/classes/api/services/CHostGroup.php +++ frontends/php/include/classes/api/services/CHostGroup.php @@ -355,7 +355,7 @@ class CHostGroup extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($group = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CHostInterface.php frontends/php/include/classes/api/services/CHostInterface.php index 4b3a839757..56b4e90b73 100644 --- frontends/php/include/classes/api/services/CHostInterface.php +++ frontends/php/include/classes/api/services/CHostInterface.php @@ -152,7 +152,7 @@ class CHostInterface extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($interface = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CHostPrototype.php frontends/php/include/classes/api/services/CHostPrototype.php index 8b67f963f6..f34d0d6bbd 100644 --- frontends/php/include/classes/api/services/CHostPrototype.php +++ frontends/php/include/classes/api/services/CHostPrototype.php @@ -103,12 +103,8 @@ class CHostPrototype extends CHostBase { if ((!$options['countOutput'] && $this->outputIsRequested('inventory_mode', $options['output'])) || ($options['filter'] && array_key_exists('inventory_mode', $options['filter']))) { - $sqlParts['left_join'][] = [ - 'from' => 'host_inventory hinv', - 'on' => $this->tableAlias().'.'.$this->pk().'=hinv.hostid' - ]; - - $sqlParts['left_table'] = array_search($this->tableName().' '.$this->tableAlias(), $sqlParts['from']); + $sqlParts['left_join'][] = ['alias' => 'hinv', 'table' => 'host_inventory', 'using' => 'hostid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } return $sqlParts; diff --git frontends/php/include/classes/api/services/CHttpTest.php frontends/php/include/classes/api/services/CHttpTest.php index 728d9afb8e..c7c726b7ea 100644 --- frontends/php/include/classes/api/services/CHttpTest.php +++ frontends/php/include/classes/api/services/CHttpTest.php @@ -199,7 +199,7 @@ class CHttpTest extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($httpTest = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CIconMap.php frontends/php/include/classes/api/services/CIconMap.php index b60b131253..333f8ce0cd 100644 --- frontends/php/include/classes/api/services/CIconMap.php +++ frontends/php/include/classes/api/services/CIconMap.php @@ -114,7 +114,7 @@ class CIconMap extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($iconMap = DBfetch($dbRes)) { if ($options['countOutput']) { $result = $iconMap['rowscount']; diff --git frontends/php/include/classes/api/services/CImage.php frontends/php/include/classes/api/services/CImage.php index eef7a977a8..5da6921fa6 100644 --- frontends/php/include/classes/api/services/CImage.php +++ frontends/php/include/classes/api/services/CImage.php @@ -129,7 +129,7 @@ class CImage extends CApiService { $imageids = []; $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($image = DBfetch($res)) { if ($options['countOutput']) { return $image['rowscount']; diff --git frontends/php/include/classes/api/services/CItem.php frontends/php/include/classes/api/services/CItem.php index af36b87e1c..86dc357c02 100644 --- frontends/php/include/classes/api/services/CItem.php +++ frontends/php/include/classes/api/services/CItem.php @@ -389,7 +389,7 @@ class CItem extends CItemGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($item = DBfetch($res)) { if (!$options['countOutput']) { $result[$item['itemid']] = $item; @@ -1204,8 +1204,8 @@ class CItem extends CItemGeneral { || $this->outputIsRequested('error', $options['output']) || (is_array($options['search']) && array_key_exists('error', $options['search'])) || (is_array($options['filter']) && array_key_exists('state', $options['filter']))) { - $sqlParts['left_join']['item_rtdata'] = ['from' => 'item_rtdata ir', 'on' => 'ir.itemid=i.itemid']; - $sqlParts['left_table'] = $tableName; + $sqlParts['left_join'][] = ['alias' => 'ir', 'table' => 'item_rtdata', 'using' => 'itemid']; + $sqlParts['left_table'] = ['alias' => $this->tableAlias, 'table' => $this->tableName]; } if (!$options['countOutput']) { diff --git frontends/php/include/classes/api/services/CItemPrototype.php frontends/php/include/classes/api/services/CItemPrototype.php index 02f850d7f8..edf2141f9c 100644 --- frontends/php/include/classes/api/services/CItemPrototype.php +++ frontends/php/include/classes/api/services/CItemPrototype.php @@ -260,7 +260,7 @@ class CItemPrototype extends CItemGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($item = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) diff --git frontends/php/include/classes/api/services/CMaintenance.php frontends/php/include/classes/api/services/CMaintenance.php index 03b73deead..e6c0ea2dca 100644 --- frontends/php/include/classes/api/services/CMaintenance.php +++ frontends/php/include/classes/api/services/CMaintenance.php @@ -219,7 +219,7 @@ class CMaintenance extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($maintenance = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CMap.php frontends/php/include/classes/api/services/CMap.php index 10beef84eb..e48e0882a9 100644 --- frontends/php/include/classes/api/services/CMap.php +++ frontends/php/include/classes/api/services/CMap.php @@ -219,7 +219,7 @@ class CMap extends CMapElement { $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); $sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); - $sysmaps = DBselect($this->createSelectQueryFromParts($sql_parts), $sql_parts['limit']); + $sysmaps = DBselect(self::createSelectQueryFromParts($sql_parts), $sql_parts['limit']); while ($sysmap = DBfetch($sysmaps)) { $result[$sysmap['sysmapid']] = $sysmap; diff --git frontends/php/include/classes/api/services/CMediatype.php frontends/php/include/classes/api/services/CMediatype.php index 6d1cc8207c..6aac6fd900 100644 --- frontends/php/include/classes/api/services/CMediatype.php +++ frontends/php/include/classes/api/services/CMediatype.php @@ -128,7 +128,7 @@ class CMediatype extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($mediatype = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CProblem.php frontends/php/include/classes/api/services/CProblem.php index c9a58d9cba..f1571398c5 100644 --- frontends/php/include/classes/api/services/CProblem.php +++ frontends/php/include/classes/api/services/CProblem.php @@ -333,7 +333,7 @@ class CProblem extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($event = DBfetch($res)) { if ($options['countOutput']) { $result = $event['rowscount']; diff --git frontends/php/include/classes/api/services/CProxy.php frontends/php/include/classes/api/services/CProxy.php index 6e4d274dd1..fc515469d9 100644 --- frontends/php/include/classes/api/services/CProxy.php +++ frontends/php/include/classes/api/services/CProxy.php @@ -121,7 +121,7 @@ class CProxy extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($proxy = DBfetch($res)) { if ($options['countOutput']) { $result = $proxy['rowscount']; diff --git frontends/php/include/classes/api/services/CScreen.php frontends/php/include/classes/api/services/CScreen.php index 1fb3c34bff..33b5d61efd 100644 --- frontends/php/include/classes/api/services/CScreen.php +++ frontends/php/include/classes/api/services/CScreen.php @@ -164,7 +164,7 @@ class CScreen extends CApiService { $screenids = []; $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); $sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); - $res = DBselect($this->createSelectQueryFromParts($sql_parts), $sql_parts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sql_parts), $sql_parts['limit']); while ($screen = DBfetch($res)) { $screenids[$screen['screenid']] = true; $result[$screen['screenid']] = $screen; diff --git frontends/php/include/classes/api/services/CScript.php frontends/php/include/classes/api/services/CScript.php index 7534b1e54b..ffab8936e8 100644 --- frontends/php/include/classes/api/services/CScript.php +++ frontends/php/include/classes/api/services/CScript.php @@ -187,7 +187,7 @@ class CScript extends CApiService { $sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); $sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts); - $result = DBselect($this->createSelectQueryFromParts($sql_parts), $options['limit']); + $result = DBselect(self::createSelectQueryFromParts($sql_parts), $options['limit']); while ($db_script = DBfetch($result)) { if ($options['countOutput']) { diff --git frontends/php/include/classes/api/services/CService.php frontends/php/include/classes/api/services/CService.php index 504b957727..ae508e4666 100644 --- frontends/php/include/classes/api/services/CService.php +++ frontends/php/include/classes/api/services/CService.php @@ -790,7 +790,7 @@ class CService extends CApiService { $sqlParts = $this->addPermissionFilter($sqlParts); } - $sql = $this->createSelectQueryFromParts($sqlParts); + $sql = self::createSelectQueryFromParts($sqlParts); return DBfetchArray(DBselect($sql)); } @@ -824,7 +824,7 @@ class CService extends CApiService { $sqlParts = $this->addPermissionFilter($sqlParts); } - $sql = $this->createSelectQueryFromParts($sqlParts); + $sql = self::createSelectQueryFromParts($sqlParts); return DBfetchArray(DBselect($sql)); } diff --git frontends/php/include/classes/api/services/CTemplate.php frontends/php/include/classes/api/services/CTemplate.php index 214d213e9c..9f1be4eccf 100644 --- frontends/php/include/classes/api/services/CTemplate.php +++ frontends/php/include/classes/api/services/CTemplate.php @@ -263,7 +263,7 @@ class CTemplate extends CHostGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($template = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CTemplateScreen.php frontends/php/include/classes/api/services/CTemplateScreen.php index 5bd9ac7cc6..e0c3d8a397 100644 --- frontends/php/include/classes/api/services/CTemplateScreen.php +++ frontends/php/include/classes/api/services/CTemplateScreen.php @@ -200,7 +200,7 @@ class CTemplateScreen extends CScreen { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($screen = DBfetch($res)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CTrigger.php frontends/php/include/classes/api/services/CTrigger.php index c0a9368ff8..a44870c863 100644 --- frontends/php/include/classes/api/services/CTrigger.php +++ frontends/php/include/classes/api/services/CTrigger.php @@ -449,7 +449,7 @@ class CTrigger extends CTriggerGeneral { // return count or grouped counts via direct SQL count if ($options['countOutput'] && !$this->requiresPostSqlFiltering($options)) { - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $options['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $options['limit']); while ($trigger = DBfetch($dbRes)) { if ($options['groupCount']) { $result[] = $trigger; @@ -461,7 +461,7 @@ class CTrigger extends CTriggerGeneral { return $result; } - $result = zbx_toHash($this->customFetch($this->createSelectQueryFromParts($sqlParts), $options), 'triggerid'); + $result = zbx_toHash($this->customFetch(self::createSelectQueryFromParts($sqlParts), $options), 'triggerid'); // return count for post SQL filtered result sets if ($options['countOutput']) { diff --git frontends/php/include/classes/api/services/CTriggerPrototype.php frontends/php/include/classes/api/services/CTriggerPrototype.php index be9d10046a..2c55440ae6 100644 --- frontends/php/include/classes/api/services/CTriggerPrototype.php +++ frontends/php/include/classes/api/services/CTriggerPrototype.php @@ -371,7 +371,7 @@ class CTriggerPrototype extends CTriggerGeneral { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $dbRes = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $dbRes = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($triggerPrototype = DBfetch($dbRes)) { if ($options['countOutput']) { if ($options['groupCount']) { diff --git frontends/php/include/classes/api/services/CUser.php frontends/php/include/classes/api/services/CUser.php index 2378dd7905..706a88fb13 100644 --- frontends/php/include/classes/api/services/CUser.php +++ frontends/php/include/classes/api/services/CUser.php @@ -168,7 +168,7 @@ class CUser extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($user = DBfetch($res)) { unset($user['passwd']); diff --git frontends/php/include/classes/api/services/CUserGroup.php frontends/php/include/classes/api/services/CUserGroup.php index a08c111e30..17015bbf88 100644 --- frontends/php/include/classes/api/services/CUserGroup.php +++ frontends/php/include/classes/api/services/CUserGroup.php @@ -139,7 +139,7 @@ class CUserGroup extends CApiService { $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($usrgrp = DBfetch($res)) { if ($options['countOutput']) { $result = $usrgrp['rowscount']; diff --git frontends/php/include/classes/api/services/CUserMacro.php frontends/php/include/classes/api/services/CUserMacro.php index 65a3bf6d6e..214828e0c4 100644 --- frontends/php/include/classes/api/services/CUserMacro.php +++ frontends/php/include/classes/api/services/CUserMacro.php @@ -195,7 +195,7 @@ class CUserMacro extends CApiService { // init GLOBALS if (!is_null($options['globalmacro'])) { $sqlPartsGlobal = $this->applyQueryOutputOptions('globalmacro', 'gm', $options, $sqlPartsGlobal); - $res = DBselect($this->createSelectQueryFromParts($sqlPartsGlobal), $sqlPartsGlobal['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlPartsGlobal), $sqlPartsGlobal['limit']); while ($macro = DBfetch($res)) { if ($options['countOutput']) { $result = $macro['rowscount']; @@ -208,7 +208,7 @@ class CUserMacro extends CApiService { // init HOSTS else { $sqlParts = $this->applyQueryOutputOptions('hostmacro', 'hm', $options, $sqlParts); - $res = DBselect($this->createSelectQueryFromParts($sqlParts), $sqlParts['limit']); + $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); while ($macro = DBfetch($res)) { if ($options['countOutput']) { $result = $macro['rowscount']; diff --git frontends/php/include/db.inc.php frontends/php/include/db.inc.php index 03fc28eb85..cd92fd4d39 100644 --- frontends/php/include/db.inc.php +++ frontends/php/include/db.inc.php @@ -666,15 +666,6 @@ function get_dbid($table, $field) { return $ret2; } -function zbx_db_distinct($sql_parts) { - $count = count($sql_parts['from']); - if (array_key_exists('left_join', $sql_parts)) { - $count += count($sql_parts['left_join']); - } - - return ($count > 1 ? ' DISTINCT' : ''); -} - function zbx_db_search($table, $options, &$sql_parts) { list($table, $tableShort) = explode(' ', $table);