@@ -93,66 +93,6 @@ def builder(self, table: str) -> AsyncQueryBuilder:
9393 qb ._query_ops = self
9494 return qb
9595
96- # --------------------------------------------------------------- fetchxml
97-
98- def fetchxml (self , xml : str ) -> AsyncFetchXmlQuery :
99- """Return an inert :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery` object.
100-
101- No HTTP request is made until
102- :meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute`
103- or
104- :meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute_pages`
105- is called on the returned object.
106-
107- :param xml: Well-formed FetchXML query string. The root ``<entity name="...">``
108- element determines the entity set endpoint.
109- :type xml: :class:`str`
110- :return: Inert async query object.
111- :rtype: :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery`
112- :raises ValidationError: If the FetchXML is not a string, is empty, or exceeds the URL
113- length limit when encoded.
114- :raises ValueError: If the FetchXML is missing a root ``<entity>`` element or name.
115-
116- Example::
117-
118- query = client.query.fetchxml(\" \" \"
119- <fetch top="50">
120- <entity name="account">
121- <attribute name="name" />
122- </entity>
123- </fetch>
124- \" \" \" )
125-
126- # Eager — all pages collected:
127- result = await query.execute()
128- df = result.to_dataframe()
129-
130- # Lazy — one page at a time:
131- async for page in query.execute_pages():
132- process(page.to_dataframe())
133- """
134- if not isinstance (xml , str ):
135- raise ValidationError ("xml must be a string" )
136- xml = xml .strip ()
137- if not xml :
138- raise ValidationError ("xml must not be empty" )
139- if len (_url_quote (xml , safe = "" )) > _MAX_URL_LENGTH :
140- raise ValidationError (
141- f"FetchXML exceeds the Dataverse URL length limit ({ _MAX_URL_LENGTH :,} characters) when encoded. "
142- "Use a $batch POST request to send FetchXML in the request body where the limit is 64 KB."
143- )
144- try :
145- root_el = _ET .fromstring (xml )
146- except _ET .ParseError as exc :
147- raise ValidationError (f"xml is not well-formed: { exc } " ) from exc
148- entity_el = root_el .find ("entity" )
149- if entity_el is None :
150- raise ValueError ("FetchXML must contain an <entity> child element" )
151- entity_name = entity_el .get ("name" , "" )
152- if not entity_name :
153- raise ValueError ("FetchXML <entity> element must have a 'name' attribute" )
154- return AsyncFetchXmlQuery (xml , entity_name , self ._client )
155-
15696 # -------------------------------------------------------------------- sql
15797
15898 async def sql (self , sql : str ) -> List [Record ]:
@@ -292,6 +232,66 @@ async def sql_columns(
292232 result .sort (key = lambda x : (not x ["is_pk" ], not x ["is_name" ], x ["name" ]))
293233 return result
294234
235+ # --------------------------------------------------------------- fetchxml
236+
237+ def fetchxml (self , xml : str ) -> AsyncFetchXmlQuery :
238+ """Return an inert :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery` object.
239+
240+ No HTTP request is made until
241+ :meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute`
242+ or
243+ :meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute_pages`
244+ is called on the returned object.
245+
246+ :param xml: Well-formed FetchXML query string. The root ``<entity name="...">``
247+ element determines the entity set endpoint.
248+ :type xml: :class:`str`
249+ :return: Inert async query object.
250+ :rtype: :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery`
251+ :raises ValidationError: If the FetchXML is not a string, is empty, or exceeds the URL
252+ length limit when encoded.
253+ :raises ValueError: If the FetchXML is missing a root ``<entity>`` element or name.
254+
255+ Example::
256+
257+ query = client.query.fetchxml(\" \" \"
258+ <fetch top="50">
259+ <entity name="account">
260+ <attribute name="name" />
261+ </entity>
262+ </fetch>
263+ \" \" \" )
264+
265+ # Eager — all pages collected:
266+ result = await query.execute()
267+ df = result.to_dataframe()
268+
269+ # Lazy — one page at a time:
270+ async for page in query.execute_pages():
271+ process(page.to_dataframe())
272+ """
273+ if not isinstance (xml , str ):
274+ raise ValidationError ("xml must be a string" )
275+ xml = xml .strip ()
276+ if not xml :
277+ raise ValidationError ("xml must not be empty" )
278+ if len (_url_quote (xml , safe = "" )) > _MAX_URL_LENGTH :
279+ raise ValidationError (
280+ f"FetchXML exceeds the Dataverse URL length limit ({ _MAX_URL_LENGTH :,} characters) when encoded. "
281+ "Use a $batch POST request to send FetchXML in the request body where the limit is 64 KB."
282+ )
283+ try :
284+ root_el = _ET .fromstring (xml )
285+ except _ET .ParseError as exc :
286+ raise ValidationError (f"xml is not well-formed: { exc } " ) from exc
287+ entity_el = root_el .find ("entity" )
288+ if entity_el is None :
289+ raise ValueError ("FetchXML must contain an <entity> child element" )
290+ entity_name = entity_el .get ("name" , "" )
291+ if not entity_name :
292+ raise ValueError ("FetchXML <entity> element must have a 'name' attribute" )
293+ return AsyncFetchXmlQuery (xml , entity_name , self ._client )
294+
295295 # =========================================================================
296296 # OData helpers -- discover columns, navigation properties, and bind values
297297 # =========================================================================
0 commit comments