This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
people/src/backend/core/utils/raw_sql.py

42 lines
1.5 KiB
Python
Raw Normal View History

"""Helper functions to generate raw SQL queries for Django models."""
from typing import Type
from django.db import models
from django.db.models.expressions import RawSQL
def gen_sql_filter_json_array(
model: Type[models.Model],
lookup_path: str,
nested_key: str,
lookup_value: str,
) -> RawSQL:
"""
Filter a queryset on a nested JSON key in an array field with
a case-insensitive and unaccent match.
Highly inspired from
https://gist.github.com/TobeTek/df2e9783a64e431c228c513441eaa8df#file-utils-py
:param Type[models.Model] model: Your Django model to filter on
:param str lookup_path: The lookup path of the array field/key in
Postgres format e.g `data->"sub-key1"->"sub-key2"`
:param str nested_key: The name of the nested key to filter on
:param str lookup_value: The value to match/filter the queryset on
"""
# Disabling S608 Possible SQL injection vector through string-based query construction
# because we are using Django's RawSQL with parameters.
# Disabling S611 Use of `RawSQL` can lead to SQL injection vulnerabilities
# for the same reason.
table_name = model._meta.db_table # noqa: SLF001
query = (
f"SELECT {table_name}.id FROM {table_name}, " # noqa: S608
f"jsonb_array_elements({lookup_path}) AS temp_filter_table "
f"WHERE unaccent(temp_filter_table->>'{nested_key}') ILIKE unaccent(%s)"
)
return RawSQL(sql=query, params=[f"%{lookup_value}%"]) # noqa: S611