Skip to content

Commit 6fc9cb8

Browse files
committed
refactor: streamline WHERE clause construction and add buildWhereClause method for improved readability and maintainability
1 parent 09c4f15 commit 6fc9cb8

1 file changed

Lines changed: 92 additions & 71 deletions

File tree

src/Usage/Adapter/ClickHouse.php

Lines changed: 92 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -989,16 +989,9 @@ public function find(array $queries = []): array
989989
$selectColumns = $this->getSelectColumns();
990990

991991
// Build WHERE clause
992-
$whereClause = '';
993-
$tenantFilter = $this->getTenantFilter();
994-
if (!empty($parsed['filters']) || $tenantFilter) {
995-
$conditions = $parsed['filters'];
996-
if ($tenantFilter) {
997-
$conditions[] = ltrim($tenantFilter, ' AND');
998-
$parsed['params']['tenant'] = $this->tenant;
999-
}
1000-
$whereClause = ' WHERE ' . implode(' AND ', $conditions);
1001-
}
992+
$whereData = $this->buildWhereClause($parsed['filters'], $parsed['params']);
993+
$whereClause = $whereData['clause'];
994+
$parsed['params'] = $whereData['params'];
1002995

1003996
// Build ORDER BY clause
1004997
$orderClause = '';
@@ -1050,25 +1043,14 @@ public function count(array $queries = []): int
10501043
// Parse queries - we only need filters and params
10511044
$parsed = $this->parseQueries($queries);
10521045

1053-
// Build WHERE clause
1054-
$whereClause = '';
1055-
$tenantFilter = $this->getTenantFilter();
1056-
if (!empty($parsed['filters']) || $tenantFilter) {
1057-
$conditions = $parsed['filters'];
1058-
if ($tenantFilter) {
1059-
$conditions[] = ltrim($tenantFilter, ' AND');
1060-
}
1061-
$whereClause = ' WHERE ' . implode(' AND ', $conditions);
1062-
}
1063-
1064-
// Remove limit and offset from params
1046+
// Remove limit and offset from params (not needed for count)
10651047
$params = $parsed['params'];
10661048
unset($params['limit'], $params['offset']);
10671049

1068-
// Add tenant param if filter is active
1069-
if ($tenantFilter) {
1070-
$params['tenant'] = $this->tenant;
1071-
}
1050+
// Build WHERE clause
1051+
$whereData = $this->buildWhereClause($parsed['filters'], $params);
1052+
$whereClause = $whereData['clause'];
1053+
$params = $whereData['params'];
10721054

10731055
// Count from both tables
10741056
$sql = "
@@ -1091,6 +1073,35 @@ public function count(array $queries = []): int
10911073
return (int) $json['data'][0]['total'];
10921074
}
10931075

1076+
/**
1077+
* Build WHERE clause from filters with optional tenant filtering.
1078+
*
1079+
* @param array<string> $filters SQL filter conditions
1080+
* @param array<string, mixed> $params Existing query parameters
1081+
* @param bool $includeTenant Whether to include tenant filter
1082+
* @return array{clause: string, params: array<string, mixed>}
1083+
*/
1084+
private function buildWhereClause(array $filters, array $params = [], bool $includeTenant = true): array
1085+
{
1086+
$conditions = $filters;
1087+
$whereParams = $params;
1088+
1089+
if ($includeTenant) {
1090+
$tenantFilter = $this->getTenantFilter();
1091+
if ($tenantFilter) {
1092+
$conditions[] = ltrim($tenantFilter, ' AND');
1093+
$whereParams['tenant'] = $this->tenant;
1094+
}
1095+
}
1096+
1097+
$clause = !empty($conditions) ? ' WHERE ' . implode(' AND ', $conditions) : '';
1098+
1099+
return [
1100+
'clause' => $clause,
1101+
'params' => $whereParams
1102+
];
1103+
}
1104+
10941105
/**
10951106
* Parse Query objects into SQL clauses.
10961107
*
@@ -1492,6 +1503,59 @@ public function getBetweenDates(string $metric, string $startDate, string $endDa
14921503
return $this->find($allQueries);
14931504
}
14941505

1506+
/**
1507+
* Sum metric values using Query objects.
1508+
* Sums from both aggregated and counter tables.
1509+
*
1510+
* @param array<Query> $queries
1511+
* @param string $attribute Attribute to sum (default: 'value')
1512+
* @return int
1513+
* @throws Exception
1514+
*/
1515+
public function sum(array $queries = [], string $attribute = 'value'): int
1516+
{
1517+
$tableName = $this->getTableName();
1518+
$counterTableName = $this->getCounterTableName();
1519+
$escapedTable = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($tableName);
1520+
$escapedCounterTable = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($counterTableName);
1521+
// FINAL on both tables (SummingMergeTree and ReplacingMergeTree)
1522+
$fromTable = $escapedTable . ($this->useFinal ? ' FINAL' : '');
1523+
$fromCounterTable = $escapedCounterTable . ($this->useFinal ? ' FINAL' : '');
1524+
1525+
// Validate attribute name
1526+
$this->validateAttributeName($attribute);
1527+
$escapedAttribute = $this->escapeIdentifier($attribute);
1528+
1529+
// Parse queries
1530+
$parsed = $this->parseQueries($queries);
1531+
1532+
// Build WHERE clause
1533+
$whereData = $this->buildWhereClause($parsed['filters'], $parsed['params']);
1534+
$whereClause = $whereData['clause'];
1535+
$params = $whereData['params'];
1536+
1537+
// Sum from both tables
1538+
$sql = "
1539+
SELECT SUM(total) as grand_total
1540+
FROM (
1541+
SELECT sum({$escapedAttribute}) as total FROM {$fromTable}{$whereClause}
1542+
UNION ALL
1543+
SELECT sum({$escapedAttribute}) as total FROM {$fromCounterTable}{$whereClause}
1544+
)
1545+
FORMAT JSON
1546+
";
1547+
1548+
$result = $this->query($sql, $params);
1549+
1550+
$json = json_decode($result, true);
1551+
1552+
if (!is_array($json) || !isset($json['data'][0]['grand_total'])) {
1553+
return 0;
1554+
}
1555+
1556+
return (int) $json['data'][0]['grand_total'];
1557+
}
1558+
14951559
/**
14961560
* Count usage metrics by period.
14971561
*
@@ -1524,60 +1588,17 @@ public function countByPeriod(string $metric, string $period, array $queries = [
15241588
*/
15251589
public function sumByPeriod(string $metric, string $period, array $queries = []): int
15261590
{
1527-
$tableName = $this->getTableName();
1528-
$counterTableName = $this->getCounterTableName();
1529-
$escapedTable = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($tableName);
1530-
$escapedCounterTable = $this->escapeIdentifier($this->database) . '.' . $this->escapeIdentifier($counterTableName);
1531-
// FINAL on both tables (SummingMergeTree and ReplacingMergeTree)
1532-
$fromTable = $escapedTable . ($this->useFinal ? ' FINAL' : '');
1533-
$fromCounterTable = $escapedCounterTable . ($this->useFinal ? ' FINAL' : '');
1534-
1535-
// Build query constraints
15361591
$allQueries = [
15371592
Query::equal('metric', [$metric]),
15381593
Query::equal('period', [$period]),
15391594
];
15401595

1596+
// Add custom queries
15411597
foreach ($queries as $query) {
15421598
$allQueries[] = $query;
15431599
}
15441600

1545-
$parsed = $this->parseQueries($allQueries);
1546-
1547-
// Build WHERE clause
1548-
$whereClause = '';
1549-
$tenantFilter = $this->getTenantFilter();
1550-
if (!empty($parsed['filters']) || $tenantFilter) {
1551-
$conditions = $parsed['filters'];
1552-
if ($tenantFilter) {
1553-
$conditions[] = ltrim($tenantFilter, ' AND');
1554-
// Add tenant param
1555-
$parsed['params']['tenant'] = $this->tenant;
1556-
}
1557-
$whereClause = ' WHERE ' . implode(' AND ', $conditions);
1558-
}
1559-
1560-
// Sum from both tables
1561-
$sql = "
1562-
SELECT SUM(total) as grand_total
1563-
FROM (
1564-
SELECT sum(value) as total FROM {$fromTable}{$whereClause}
1565-
UNION ALL
1566-
SELECT sum(value) as total FROM {$fromCounterTable}{$whereClause}
1567-
)
1568-
1569-
FORMAT JSON
1570-
";
1571-
1572-
$result = $this->query($sql, $parsed['params']);
1573-
1574-
$json = json_decode($result, true);
1575-
1576-
if (!is_array($json) || !isset($json['data'][0]['grand_total'])) {
1577-
return 0;
1578-
}
1579-
1580-
return (int) $json['data'][0]['grand_total'];
1601+
return $this->sum($allQueries);
15811602
}
15821603

15831604
/**

0 commit comments

Comments
 (0)