|
| 1 | +__all__ = ["AQL"] |
| 2 | + |
| 3 | + |
| 4 | +from typing import Optional |
| 5 | + |
| 6 | +from arangoasync.cursor import Cursor |
| 7 | +from arangoasync.exceptions import AQLQueryExecuteError |
| 8 | +from arangoasync.executor import ApiExecutor |
| 9 | +from arangoasync.request import Method, Request |
| 10 | +from arangoasync.response import Response |
| 11 | +from arangoasync.serialization import Deserializer, Serializer |
| 12 | +from arangoasync.typings import Json, Jsons, QueryProperties, Result |
| 13 | + |
| 14 | + |
| 15 | +class AQL: |
| 16 | + """AQL (ArangoDB Query Language) API wrapper. |
| 17 | +
|
| 18 | + Allows you to execute, track, kill, explain, and validate queries written |
| 19 | + in ArangoDB’s query language. |
| 20 | +
|
| 21 | + Args: |
| 22 | + executor: API executor. Required to execute the API requests. |
| 23 | + """ |
| 24 | + |
| 25 | + def __init__(self, executor: ApiExecutor) -> None: |
| 26 | + self._executor = executor |
| 27 | + |
| 28 | + @property |
| 29 | + def name(self) -> str: |
| 30 | + """Return the name of the current database.""" |
| 31 | + return self._executor.db_name |
| 32 | + |
| 33 | + @property |
| 34 | + def serializer(self) -> Serializer[Json]: |
| 35 | + """Return the serializer.""" |
| 36 | + return self._executor.serializer |
| 37 | + |
| 38 | + @property |
| 39 | + def deserializer(self) -> Deserializer[Json, Jsons]: |
| 40 | + """Return the deserializer.""" |
| 41 | + return self._executor.deserializer |
| 42 | + |
| 43 | + def __repr__(self) -> str: |
| 44 | + return f"<AQL in {self.name}>" |
| 45 | + |
| 46 | + async def execute( |
| 47 | + self, |
| 48 | + query: str, |
| 49 | + count: Optional[bool] = None, |
| 50 | + batch_size: Optional[int] = None, |
| 51 | + bind_vars: Optional[Json] = None, |
| 52 | + cache: Optional[bool] = None, |
| 53 | + memory_limit: Optional[int] = None, |
| 54 | + ttl: Optional[int] = None, |
| 55 | + allow_dirty_read: Optional[bool] = None, |
| 56 | + options: Optional[QueryProperties] = None, |
| 57 | + ) -> Result[Cursor]: |
| 58 | + """Execute the query and return the result cursor. |
| 59 | +
|
| 60 | + Args: |
| 61 | + query (str): Query string to be executed. |
| 62 | + count (bool | None): If set to `True`, the total document count is |
| 63 | + calculated and included in the result cursor. |
| 64 | + batch_size (int | None): Maximum number of result documents to be |
| 65 | + transferred from the server to the client in one roundtrip. |
| 66 | + bind_vars (dict | None): An object with key/value pairs representing |
| 67 | + the bind parameters. |
| 68 | + cache (bool | None): Flag to determine whether the AQL query results |
| 69 | + cache shall be used. |
| 70 | + memory_limit (int | None): Maximum memory (in bytes) that the query is |
| 71 | + allowed to use. |
| 72 | + ttl (int | None): The time-to-live for the cursor (in seconds). The cursor |
| 73 | + will be removed on the server automatically after the specified amount |
| 74 | + of time. |
| 75 | + allow_dirty_read (bool | None): Allow reads from followers in a cluster. |
| 76 | + options (QueryProperties | None): Extra options for the query. |
| 77 | +
|
| 78 | + References: |
| 79 | + - `create-a-cursor <https://docs.arangodb.com/stable/develop/http-api/queries/aql-queries/#create-a-cursor>`__ |
| 80 | + """ # noqa: E501 |
| 81 | + data: Json = dict(query=query) |
| 82 | + if count is not None: |
| 83 | + data["count"] = count |
| 84 | + if batch_size is not None: |
| 85 | + data["batchSize"] = batch_size |
| 86 | + if bind_vars is not None: |
| 87 | + data["bindVars"] = bind_vars |
| 88 | + if cache is not None: |
| 89 | + data["cache"] = cache |
| 90 | + if memory_limit is not None: |
| 91 | + data["memoryLimit"] = memory_limit |
| 92 | + if ttl is not None: |
| 93 | + data["ttl"] = ttl |
| 94 | + if options is not None: |
| 95 | + data["options"] = options.to_dict() |
| 96 | + |
| 97 | + headers = dict() |
| 98 | + if allow_dirty_read is not None: |
| 99 | + headers["x-arango-allow-dirty-read"] = str(allow_dirty_read).lower() |
| 100 | + |
| 101 | + request = Request( |
| 102 | + method=Method.POST, |
| 103 | + endpoint="/_api/cursor", |
| 104 | + data=self.serializer.dumps(data), |
| 105 | + headers=headers, |
| 106 | + ) |
| 107 | + |
| 108 | + def response_handler(resp: Response) -> Cursor: |
| 109 | + if not resp.is_success: |
| 110 | + raise AQLQueryExecuteError(resp, request) |
| 111 | + return Cursor(self._executor, self.deserializer.loads(resp.raw_body)) |
| 112 | + |
| 113 | + return await self._executor.execute(request, response_handler) |
0 commit comments