Skip to content

Commit 0f843bb

Browse files
lohanidamodarclaude
andcommitted
fix: reject empty values for filter methods that require them
Mirrors the validator pattern in utopia-php/database (Validator/Query/Filter.php): contains/notContains/equal/etc. queries must have at least one value; an empty values array is rejected up front with `<Method> queries require at least one value.` instead of silently producing a "no filter applied" WHERE clause. Without the guard, `Query::contains('metric', [])` would skip the IN clause entirely and return all rows — exactly the opposite of the intended IN () semantics, which should match nothing. Applies the same VALUE_REQUIRED_METHODS allow-list and pre-switch check that the audit adapter uses, so both libraries reject the same set of empty-value filter methods consistently. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a456325 commit 0f843bb

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

src/Usage/Adapter/ClickHouse.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ class ClickHouse extends SQL
4848
'1d' => 'toStartOfDay',
4949
];
5050

51+
/**
52+
* Filter methods that must be supplied at least one value. Empty `values`
53+
* arrays for these methods are rejected up front so they can't silently
54+
* compile into a "no filter applied" WHERE clause.
55+
*
56+
* @var list<string>
57+
*/
58+
private const VALUE_REQUIRED_METHODS = [
59+
Query::TYPE_EQUAL,
60+
Query::TYPE_NOT_EQUAL,
61+
Query::TYPE_LESSER,
62+
Query::TYPE_LESSER_EQUAL,
63+
Query::TYPE_GREATER,
64+
Query::TYPE_GREATER_EQUAL,
65+
Query::TYPE_BETWEEN,
66+
Query::TYPE_NOT_BETWEEN,
67+
Query::TYPE_CONTAINS,
68+
Query::TYPE_NOT_CONTAINS,
69+
Query::TYPE_STARTS_WITH,
70+
Query::TYPE_ENDS_WITH,
71+
];
72+
5173
private string $host;
5274

5375
private int $port;
@@ -2665,6 +2687,15 @@ private function parseQueries(array $queries, string $type = 'event'): array
26652687
$attribute = $query->getAttribute();
26662688
$values = $query->getValues();
26672689

2690+
// Reject empty values for filter methods that take values — mirrors
2691+
// the validator in utopia-php/database (Validator/Query/Filter.php)
2692+
// and prevents silently dropping the WHERE fragment, which would
2693+
// otherwise turn `Query::contains('attr', [])` into a full-table
2694+
// match instead of an empty result.
2695+
if (\in_array($method, self::VALUE_REQUIRED_METHODS, true) && empty($values)) {
2696+
throw new \Exception(\ucfirst($method) . ' queries require at least one value.');
2697+
}
2698+
26682699
switch ($method) {
26692700
case Query::TYPE_EQUAL:
26702701
$this->validateAttributeName($attribute, $type);

tests/Usage/Adapter/ClickHouseTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,4 +1160,34 @@ public function testStartsWithAndEndsWithQueries(): void
11601160
$this->assertStringEndsWith('/files', $path);
11611161
}
11621162
}
1163+
1164+
public function testContainsRejectsEmptyValues(): void
1165+
{
1166+
$this->expectException(\Exception::class);
1167+
$this->expectExceptionMessage('Contains queries require at least one value.');
1168+
1169+
$this->usage->find([
1170+
Query::contains('metric', []),
1171+
], Usage::TYPE_EVENT);
1172+
}
1173+
1174+
public function testNotContainsRejectsEmptyValues(): void
1175+
{
1176+
$this->expectException(\Exception::class);
1177+
$this->expectExceptionMessage('NotContains queries require at least one value.');
1178+
1179+
$this->usage->find([
1180+
Query::notContains('metric', []),
1181+
], Usage::TYPE_EVENT);
1182+
}
1183+
1184+
public function testEqualRejectsEmptyValues(): void
1185+
{
1186+
$this->expectException(\Exception::class);
1187+
$this->expectExceptionMessage('Equal queries require at least one value.');
1188+
1189+
$this->usage->find([
1190+
new Query(Query::TYPE_EQUAL, 'metric', []),
1191+
], Usage::TYPE_EVENT);
1192+
}
11631193
}

0 commit comments

Comments
 (0)