diff --git a/src/diracx/db/sql/jobs/db.py b/src/diracx/db/sql/jobs/db.py index d4034b68..329dd2bc 100644 --- a/src/diracx/db/sql/jobs/db.py +++ b/src/diracx/db/sql/jobs/db.py @@ -68,7 +68,14 @@ async def summary(self, group_by, search) -> list[dict[str, str | int]]: ] async def search( - self, parameters, search, sorts, *, per_page: int = 100, page: int | None = None + self, + parameters, + search, + sorts, + *, + distinct: bool = False, + per_page: int = 100, + page: int | None = None, ) -> list[dict[str, Any]]: # Find which columns to select columns = _get_columns(Jobs.__table__, parameters) @@ -90,6 +97,9 @@ async def search( else: raise InvalidQueryError(f"Unknown sort {sort['direction']=}") + if distinct: + stmt = stmt.distinct() + # Apply pagination if page: raise NotImplementedError("TODO Not yet implemented") diff --git a/src/diracx/routers/job_manager/__init__.py b/src/diracx/routers/job_manager/__init__.py index 987a8252..baa0c134 100644 --- a/src/diracx/routers/job_manager/__init__.py +++ b/src/diracx/routers/job_manager/__init__.py @@ -53,6 +53,7 @@ class JobSearchParams(BaseModel): parameters: list[str] | None = None search: list[SearchSpec] = [] sort: list[SortSpec] = [] + distinct: bool = False @root_validator def validate_fields(cls, v): @@ -443,7 +444,12 @@ async def search( ) # TODO: Pagination return await job_db.search( - body.parameters, body.search, body.sort, page=page, per_page=per_page + body.parameters, + body.search, + body.sort, + distinct=body.distinct, + page=page, + per_page=per_page, ) diff --git a/tests/routers/test_job_manager.py b/tests/routers/test_job_manager.py index c40082b8..0b2a335d 100644 --- a/tests/routers/test_job_manager.py +++ b/tests/routers/test_job_manager.py @@ -195,6 +195,25 @@ def test_insert_and_search(normal_user_client): assert r.json() == [] +def test_search_distinct(normal_user_client): + job_definitions = [TEST_JDL, TEST_JDL, TEST_JDL] + r = normal_user_client.post("/api/jobs/", json=job_definitions) + assert r.status_code == 200, r.json() + assert len(r.json()) == len(job_definitions) + + # Check that distinct collapses identical records when true + r = normal_user_client.post( + "/api/jobs/search", json={"parameters": ["Status"], "distinct": False} + ) + assert r.status_code == 200, r.json() + assert len(r.json()) > 1 + r = normal_user_client.post( + "/api/jobs/search", json={"parameters": ["Status"], "distinct": True} + ) + assert r.status_code == 200, r.json() + assert len(r.json()) == 1 + + def test_user_cannot_submit_parametric_jdl_greater_than_max_parametric_jobs( normal_user_client, ):