From f0ef328db5fc34db87070dc83e3af9d382a74eed Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 13 Apr 2022 12:49:41 +0200 Subject: [statistics] Add PCI device filter option --- .../statistics/inc/hardwarequery.inc.php | 16 +++++---- .../statistics/inc/hardwarequerycolumn.inc.php | 6 ++-- .../statistics/inc/statisticsfilter.inc.php | 40 ++++++++++++++++++++-- 3 files changed, 51 insertions(+), 11 deletions(-) (limited to 'modules-available/statistics/inc') diff --git a/modules-available/statistics/inc/hardwarequery.inc.php b/modules-available/statistics/inc/hardwarequery.inc.php index 00a9bbc9..93793e58 100644 --- a/modules-available/statistics/inc/hardwarequery.inc.php +++ b/modules-available/statistics/inc/hardwarequery.inc.php @@ -120,7 +120,7 @@ class HardwareQuery /** * @return false|PDOStatement */ - public function query(string $groupBy = '') + public function query($groupBy = '') { return Database::simpleQuery($this->buildQuery($groupBy), $this->args); } @@ -129,13 +129,17 @@ class HardwareQuery * Build query string * @param string $groupBy Column to group by */ - public function buildQuery(string $groupBy = ''): string + public function buildQuery($groupBy = ''): string { - $groupConcat = !empty($groupBy) && $groupBy !== 'mxhw.machinehwid'; + if (empty($groupBy)) { + $groupBy = []; + } elseif (!is_array($groupBy)) { + $groupBy = [$groupBy]; + } $columns = []; foreach ($this->columns as $column) { if ($column instanceof HardwareQueryColumn) { - $column->generate($this->joins, $columns, $this->args, $groupConcat); + $column->generate($this->joins, $columns, $this->args, $groupBy); } else { $columns[] = $column; } @@ -143,14 +147,14 @@ class HardwareQuery $columns[] = 'mxhw.machineuuid'; $columns[] = 'shw.hwid'; // TODO: Untangle this implicit magic - if (empty($groupBy) || $groupBy === 'mxhw.machinehwid') { + if (empty($groupBy) || $groupBy[0] === 'mxhw.machinehwid') { $columns[] = 'mxhw.disconnecttime'; } else { $columns[] = 'Sum(If(mxhw.disconnecttime = 0, 1, 0)) AS connected_count'; } if (!empty($groupBy)) { $columns[] = 'Count(*) AS group_count'; - $groupBy = " GROUP BY $groupBy"; + $groupBy = " GROUP BY " . implode(', ', $groupBy); } return 'SELECT ' . implode(', ', $columns) . ' FROM statistic_hw shw ' diff --git a/modules-available/statistics/inc/hardwarequerycolumn.inc.php b/modules-available/statistics/inc/hardwarequerycolumn.inc.php index d073530b..5e16bcd9 100644 --- a/modules-available/statistics/inc/hardwarequerycolumn.inc.php +++ b/modules-available/statistics/inc/hardwarequerycolumn.inc.php @@ -30,9 +30,9 @@ class HardwareQueryColumn /** * Add necessary conditions, joins, columns to final SQL arrays. To be called * from HardwareQuery::buildQuery(). - * @param bool $groupConcat whether to add distinct GROUP_CONCAT to column. + * @param array if column name is in this array, add as distinct GROUP_CONCAT to column. */ - public function generate(array &$joins, array &$columns, array &$params, bool $groupConcat) + public function generate(array &$joins, array &$columns, array &$params, array $groupConcat = []) { if ($this->global) { $srcTable = 'shw'; @@ -53,7 +53,7 @@ class HardwareQueryColumn // INNER JOIN, so the result will be empty if the condition doesn't match. $type = count($this->conditions) === 1 ? 'LEFT' : 'INNER'; $joins[] = "$type JOIN $table $tid ON (" . implode(' AND ', $this->conditions) . ")"; - if ($groupConcat) { + if (!in_array($this->alias, $groupConcat)) { $columns[] = "Group_Concat(DISTINCT $tid.`value` SEPARATOR ', ') AS `{$this->alias}`"; } else { $columns[] = "$tid.`value` AS `{$this->alias}`"; diff --git a/modules-available/statistics/inc/statisticsfilter.inc.php b/modules-available/statistics/inc/statisticsfilter.inc.php index a4e96294..1c3df9af 100644 --- a/modules-available/statistics/inc/statisticsfilter.inc.php +++ b/modules-available/statistics/inc/statisticsfilter.inc.php @@ -253,6 +253,7 @@ abstract class StatisticsFilter 'live_memfree' => new SimpleStatisticsFilter('live_memfree', self::OP_ORDINAL, 'MiB'), 'live_tmpfree' => new SimpleStatisticsFilter('live_tmpfree', self::OP_ORDINAL, 'MiB'), 'standbycrash' => new StandbyCrashStatisticsFilter(), + 'pcidev' => new PciDeviceStatisticsFilter(), ]; if (Module::isAvailable('locations')) { self::$columns['location'] = new LocationStatisticsFilter(); @@ -617,15 +618,50 @@ class IsClientStatisticsFilter extends StatisticsFilter public function whereClause(string $operator, $argument, array &$args, array &$joins): string { if ($argument) { - $joins[] = ' LEFT JOIN runmode USING (machineuuid)'; + $joins[] = ' LEFT JOIN runmode ON (m.machineuuid = runmode.machineuuid)'; return "(runmode.isclient <> 0 OR runmode.isclient IS NULL)"; } - $joins[] = ' INNER JOIN runmode USING (machineuuid)'; + $joins[] = ' INNER JOIN runmode ON (m.machineuuid = runmode.machineuuid)'; return "runmode.isclient = 0"; } } +class PciDeviceStatisticsFilter extends StatisticsFilter +{ + + public function __construct() + { + parent::__construct(null, ['=']); + } + + public function whereClause(string $operator, $argument, array &$args, array &$joins): string + { + if (!preg_match('/^([0-9a-f]{4})(?::([0-9a-f]{4}))?$/i', $argument, $out)) { + Message::addError('invalid-pciid', $argument); + return '0'; + } + $vendor = $out[1]; + $device = $out[2] ?? ''; + // basic join for hw_x_machine + $joins[] = ' INNER JOIN machine_x_hw mxhw ON (mxhw.disconnecttime = 0 AND mxhw.machineuuid = m.machineuuid)'; + $key = $key = self::getNewKey('foo'); + $joins[] = " INNER JOIN statistic_hw shw ON (mxhw.hwid = shw.hwid AND shw.hwtype = :$key)"; + $args[$key] = HardwareInfo::PCI_DEVICE; + $_ = []; + $c = new HardwareQueryColumn(true, 'vendor'); + $c->addCondition($operator, $vendor); + $c->generate($joins, $_, $args); + if (!empty($device)) { + $c = new HardwareQueryColumn(true, 'device'); + $c->addCondition($operator, $device); + $c->generate($joins, $_, $args); + } + return '1'; + } + +} + class DatabaseFilter { /** @var StatisticsFilter -- cgit v1.2.3-55-g7522