ILIKE généralisé dans API/MCP pour contains

This commit is contained in:
Colin Maudry
2026-07-14 21:23:07 +02:00
parent d920e1ca8e
commit 17e9c33934
4 changed files with 11 additions and 9 deletions
+3 -3
View File
@@ -182,13 +182,13 @@ def build_where(
where_parts.append(f'"{col}" {op_sql[op]} ?') where_parts.append(f'"{col}" {op_sql[op]} ?')
params.append(v) params.append(v)
elif op == "contains": elif op == "contains":
where_parts.append(f'"{col}" LIKE ?') where_parts.append(f'"{col}" ILIKE ?')
params.append(f"%{v}%") params.append(f"%{v}%")
elif op == "notcontains": elif op == "notcontains":
where_parts.append(f'"{col}" NOT LIKE ?') where_parts.append(f'"{col}" NOT ILIKE ?')
params.append(f"%{v}%") params.append(f"%{v}%")
elif op == "startswith": elif op == "startswith":
where_parts.append(f'"{col}" LIKE ?') where_parts.append(f'"{col}" ILIKE ?')
params.append(f"{v}%") params.append(f"{v}%")
elif op == "differs": elif op == "differs":
where_parts.append(f'"{col}" IS DISTINCT FROM ?') where_parts.append(f'"{col}" IS DISTINCT FROM ?')
+4 -2
View File
@@ -130,8 +130,10 @@ def schema():
"**Filtres** (`<colonne>__<op>=<valeur>`) :\n" "**Filtres** (`<colonne>__<op>=<valeur>`) :\n"
"- `exact` : égal à la valeur\n" "- `exact` : égal à la valeur\n"
"- `differs` : différent de la valeur (null-safe, `IS DISTINCT FROM`)\n" "- `differs` : différent de la valeur (null-safe, `IS DISTINCT FROM`)\n"
"- `contains` / `notcontains` : contient / ne contient pas (LIKE)\n" "- `contains` / `notcontains` : contient / ne contient pas "
"- `startswith` : commence par (préfixe, ex. `codeCPV__startswith=72`)\n" "(insensible à la casse)\n"
"- `startswith` : commence par (préfixe, insensible à la casse, "
"ex. `codeCPV__startswith=72`)\n"
"- `in` / `notin` : dans / hors d'une liste séparée par des virgules\n" "- `in` / `notin` : dans / hors d'une liste séparée par des virgules\n"
"- `less` / `greater` : ≤ / ≥\n" "- `less` / `greater` : ≤ / ≥\n"
"- `strictly_less` / `strictly_greater` : < / >\n" "- `strictly_less` / `strictly_greater` : < / >\n"
+1 -1
View File
@@ -131,7 +131,7 @@ def prompt_tips():
html.Ul([html.Li(html.Em(f"« {p} »")) for p in exemples]), html.Ul([html.Li(html.Em(f"« {p} »")) for p in exemples]),
html.P( html.P(
"Astuce colonnes : demandez à l'assistant de vous proposer les " "Astuce colonnes : demandez à l'assistant de vous proposer les "
"colonnes disponibles pour choisir précisément ce qui s'affiche sous la forme, si possible d'une liste de cases à cocher " "colonnes disponibles pour choisir précisément ce qui s'affiche, si possible sous la forme d'une liste de cases à cocher "
"(les colonnes par défaut restent pré-sélectionnées). Chaque " "(les colonnes par défaut restent pré-sélectionnées). Chaque "
"marché renvoyé inclut un lien direct vers sa fiche sur colibre.", "marché renvoyé inclut un lien direct vers sa fiche sur colibre.",
className="text-muted", className="text-muted",
+3 -3
View File
@@ -29,19 +29,19 @@ def test_exact_filter():
def test_contains_filter_uses_like_wildcards(): def test_contains_filter_uses_like_wildcards():
where, params, _ = build_where([("objet__contains", "informatique")], SCHEMA) where, params, _ = build_where([("objet__contains", "informatique")], SCHEMA)
assert where == '"objet" LIKE ?' assert where == '"objet" ILIKE ?'
assert params == ["%informatique%"] assert params == ["%informatique%"]
def test_notcontains_filter(): def test_notcontains_filter():
where, params, _ = build_where([("objet__notcontains", "x")], SCHEMA) where, params, _ = build_where([("objet__notcontains", "x")], SCHEMA)
assert where == '"objet" NOT LIKE ?' assert where == '"objet" NOT ILIKE ?'
assert params == ["%x%"] assert params == ["%x%"]
def test_startswith_filter_uses_prefix_wildcard(): def test_startswith_filter_uses_prefix_wildcard():
where, params, _ = build_where([("objet__startswith", "72")], SCHEMA) where, params, _ = build_where([("objet__startswith", "72")], SCHEMA)
assert where == '"objet" LIKE ?' assert where == '"objet" ILIKE ?'
assert params == ["72%"] assert params == ["72%"]