Skip to content

Commit 3c32b76

Browse files
Made entity service folder aware
1 parent c9fdba4 commit 3c32b76

3 files changed

Lines changed: 61 additions & 8 deletions

File tree

packages/uipath-platform/src/uipath/platform/entities/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
EntityFieldMetadata,
1111
EntityRecord,
1212
EntityRecordsBatchResponse,
13+
EntityRouting,
1314
ExternalField,
1415
ExternalObject,
1516
ExternalSourceFields,
1617
FieldDataType,
1718
FieldMetadata,
19+
QueryRoutingContext,
1820
ReferenceType,
1921
SourceJoinCriteria,
2022
)
@@ -25,12 +27,14 @@
2527
"EntityField",
2628
"EntityRecord",
2729
"EntityFieldMetadata",
30+
"EntityRouting",
2831
"FieldDataType",
2932
"FieldMetadata",
3033
"EntityRecordsBatchResponse",
3134
"ExternalField",
3235
"ExternalObject",
3336
"ExternalSourceFields",
37+
"QueryRoutingContext",
3438
"ReferenceType",
3539
"SourceJoinCriteria",
3640
]

packages/uipath-platform/src/uipath/platform/entities/_entities_service.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Entity,
1515
EntityRecord,
1616
EntityRecordsBatchResponse,
17+
QueryRoutingContext,
1718
)
1819

1920
_FORBIDDEN_DML = {"INSERT", "UPDATE", "DELETE", "MERGE", "REPLACE"}
@@ -416,6 +417,7 @@ class CustomerRecord:
416417
def query_entity_records(
417418
self,
418419
sql_query: str,
420+
routing_context: Optional["QueryRoutingContext"] = None,
419421
) -> List[Dict[str, Any]]:
420422
"""Query entity records using a validated SQL query.
421423
@@ -425,6 +427,9 @@ def query_entity_records(
425427
sql_query (str): A SQL SELECT query to execute against Data Service entities.
426428
Only SELECT statements are allowed. Queries without WHERE must include
427429
a LIMIT clause. Subqueries and multi-statement queries are not permitted.
430+
routing_context (Optional[QueryRoutingContext]): Per-entity routing context
431+
for multi-folder queries. When present, included in the request body
432+
and takes precedence over the folder header on the backend.
428433
429434
Returns:
430435
List[Dict[str, Any]]: A list of result records as dictionaries.
@@ -433,12 +438,15 @@ def query_entity_records(
433438
ValueError: If the SQL query fails validation (e.g., non-SELECT, missing
434439
WHERE/LIMIT, forbidden keywords, subqueries).
435440
"""
436-
return self._query_entities_for_records(sql_query)
441+
return self._query_entities_for_records(
442+
sql_query, routing_context=routing_context
443+
)
437444

438445
@traced(name="entity_query_records", run_type="uipath")
439446
async def query_entity_records_async(
440447
self,
441448
sql_query: str,
449+
routing_context: Optional["QueryRoutingContext"] = None,
442450
) -> List[Dict[str, Any]]:
443451
"""Asynchronously query entity records using a validated SQL query.
444452
@@ -448,6 +456,9 @@ async def query_entity_records_async(
448456
sql_query (str): A SQL SELECT query to execute against Data Service entities.
449457
Only SELECT statements are allowed. Queries without WHERE must include
450458
a LIMIT clause. Subqueries and multi-statement queries are not permitted.
459+
routing_context (Optional[QueryRoutingContext]): Per-entity routing context
460+
for multi-folder queries. When present, included in the request body
461+
and takes precedence over the folder header on the backend.
451462
452463
Returns:
453464
List[Dict[str, Any]]: A list of result records as dictionaries.
@@ -456,20 +467,32 @@ async def query_entity_records_async(
456467
ValueError: If the SQL query fails validation (e.g., non-SELECT, missing
457468
WHERE/LIMIT, forbidden keywords, subqueries).
458469
"""
459-
return await self._query_entities_for_records_async(sql_query)
470+
return await self._query_entities_for_records_async(
471+
sql_query, routing_context=routing_context
472+
)
460473

461-
def _query_entities_for_records(self, sql_query: str) -> List[Dict[str, Any]]:
474+
def _query_entities_for_records(
475+
self,
476+
sql_query: str,
477+
*,
478+
routing_context: Optional["QueryRoutingContext"] = None,
479+
) -> List[Dict[str, Any]]:
462480
self._validate_sql_query(sql_query)
463-
spec = self._query_entity_records_spec(sql_query)
481+
spec = self._query_entity_records_spec(sql_query, routing_context)
464482
response = self.request(spec.method, spec.endpoint, json=spec.json)
465483
return response.json().get("results", [])
466484

467485
async def _query_entities_for_records_async(
468-
self, sql_query: str
486+
self,
487+
sql_query: str,
488+
*,
489+
routing_context: Optional["QueryRoutingContext"] = None,
469490
) -> List[Dict[str, Any]]:
470491
self._validate_sql_query(sql_query)
471-
spec = self._query_entity_records_spec(sql_query)
472-
response = await self.request_async(spec.method, spec.endpoint, json=spec.json)
492+
spec = self._query_entity_records_spec(sql_query, routing_context)
493+
response = await self.request_async(
494+
spec.method, spec.endpoint, json=spec.json
495+
)
473496
return response.json().get("results", [])
474497

475498
@traced(name="entity_record_insert_batch", run_type="uipath")
@@ -958,11 +981,17 @@ def _list_records_spec(
958981
def _query_entity_records_spec(
959982
self,
960983
sql_query: str,
984+
routing_context: Optional["QueryRoutingContext"] = None,
961985
) -> RequestSpec:
986+
body: Dict[str, Any] = {"query": sql_query}
987+
if routing_context:
988+
body["routingContext"] = routing_context.model_dump(
989+
by_alias=True, exclude_none=True
990+
)
962991
return RequestSpec(
963992
method="POST",
964993
endpoint=Endpoint("datafabric_/api/v1/query/execute"),
965-
json={"query": sql_query},
994+
json=body,
966995
)
967996

968997
def _insert_batch_spec(self, entity_key: str, records: List[Any]) -> RequestSpec:

packages/uipath-platform/src/uipath/platform/entities/entities.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,24 @@ class EntityRecordsBatchResponse(BaseModel):
322322
failure_records: List[EntityRecord] = Field(alias="failureRecords")
323323

324324

325+
class EntityRouting(BaseModel):
326+
"""A single entity-to-folder routing entry for query execution."""
327+
328+
model_config = ConfigDict(populate_by_name=True)
329+
330+
entity_name: str = Field(alias="entityName")
331+
folder_id: str = Field(alias="folderId")
332+
override_entity_name: Optional[str] = Field(
333+
default=None, alias="overrideEntityName"
334+
)
335+
336+
337+
class QueryRoutingContext(BaseModel):
338+
"""Routing context that maps entities to their folders for multi-entity queries."""
339+
340+
model_config = ConfigDict(populate_by_name=True)
341+
342+
entity_routings: List[EntityRouting] = Field(alias="entityRoutings")
343+
344+
325345
Entity.model_rebuild()

0 commit comments

Comments
 (0)