feat(api): ajoute l'opérateur de filtre differs (IS DISTINCT FROM) (#78)

Implémente l'opérateur de filtre `differs` qui génère un fragment SQL
`IS DISTINCT FROM` pour exclure des valeurs en tenant compte des NULL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Colin Maudry
2026-06-22 13:55:18 +02:00
parent f5db674e22
commit 2a8e82ccd6
3 changed files with 26 additions and 0 deletions
+4
View File
@@ -6,6 +6,7 @@ OPERATORS = {
"exact", "exact",
"contains", "contains",
"notcontains", "notcontains",
"differs",
"less", "less",
"greater", "greater",
"strictly_less", "strictly_less",
@@ -132,6 +133,9 @@ def build_where(
elif op == "notcontains": elif op == "notcontains":
where_parts.append(f'"{col}" NOT LIKE ?') where_parts.append(f'"{col}" NOT LIKE ?')
params.append(f"%{v}%") params.append(f"%{v}%")
elif op == "differs":
where_parts.append(f'"{col}" IS DISTINCT FROM ?')
params.append(v)
where_sql = " AND ".join(where_parts) if where_parts else "TRUE" where_sql = " AND ".join(where_parts) if where_parts else "TRUE"
order_sql = ", ".join(order_parts) if order_parts else None order_sql = ", ".join(order_parts) if order_parts else None
+10
View File
@@ -102,3 +102,13 @@ def test_data_sort_desc(api_client, valid_token_header):
row["dateNotification"] for row in body["data"] if row.get("dateNotification") row["dateNotification"] for row in body["data"] if row.get("dateNotification")
] ]
assert dates == sorted(dates, reverse=True) assert dates == sorted(dates, reverse=True)
def test_data_differs_excludes_value(api_client, valid_token_header):
client, _ = api_client
base = client.get("/api/v1/data?page_size=1", headers=valid_token_header).get_json()
uid = base["data"][0]["uid"]
resp = client.get(f"/api/v1/data?uid__differs={uid}", headers=valid_token_header)
assert resp.status_code == 200
body = resp.get_json()
assert all(row["uid"] != uid for row in body["data"])
+12
View File
@@ -139,3 +139,15 @@ def test_sort_invalid_direction_raises():
def test_param_without_operator_raises(): def test_param_without_operator_raises():
with pytest.raises(FilterError): with pytest.raises(FilterError):
build_where([("uidexact", "x")], SCHEMA) build_where([("uidexact", "x")], SCHEMA)
def test_differs_filter():
where, params, _ = build_where([("uid__differs", "abc")], SCHEMA)
assert where == '"uid" IS DISTINCT FROM ?'
assert params == ["abc"]
def test_differs_filter_on_int():
where, params, _ = build_where([("annee__differs", "2020")], SCHEMA)
assert where == '"annee" IS DISTINCT FROM ?'
assert params == [2020]