Skip to content

Commit 7fd464f

Browse files
authored
Feat: introduce error handler callbacks (#5)
add support for optional error handling callback for cases like malformed or unexpected responses
1 parent de1eaa7 commit 7fd464f

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

py_questdb/db.py

+23-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Module for interacting with QuestDB."""
22

33
from types import TracebackType
4-
from typing import Iterable, Type, overload, AsyncGenerator, Any, TypeVar
4+
from typing import Iterable, Type, overload, AsyncGenerator, Any, TypeVar, Callable
55

66
import aiohttp
77
import pandas as pd
@@ -156,18 +156,27 @@ async def query(self, query_string: str) -> AsyncGenerator[dict[str, Any], None]
156156
@overload
157157
async def query(self, query_string: str, into_type: Type[T]) -> AsyncGenerator[T, None]: ...
158158

159-
async def query(self, query_string: str, into_type: Type[T] | None = None) -> AsyncGenerator[T, None]:
159+
async def query(
160+
self, query_string: str, into_type: Type[T] | None = None, error_handler: Callable[[bytes], None] | None = None
161+
) -> AsyncGenerator[T, None]:
160162
"""
161163
Perform an asynchronous query and yield the results.
162164
163165
Args:
164166
query_string: The SQL query string to execute.
165167
into_type: Optional type to cast each row into.
168+
error_handler: Optional function to handle errors in the response.
166169
167170
Yields:
168171
Parsed rows as either dictionaries or instances of the specified type.
169172
"""
170-
data = self.parse_query_response(await self._query(query_string))
173+
query_response = await self._query(query_string)
174+
try:
175+
data = self.parse_query_response(query_response)
176+
except Exception as e:
177+
if error_handler:
178+
error_handler(query_response)
179+
raise e
171180

172181
for row in self.parse_and_yield_query_response(data, into_type):
173182
yield row
@@ -178,18 +187,26 @@ def query_sync(self, query_string: str) -> Iterable[dict[str, Any]]: ...
178187
@overload
179188
def query_sync(self, query_string: str, into_type: Type[T]) -> Iterable[T]: ...
180189

181-
def query_sync(self, query_string: str, into_type: Type[T] | None = None) -> Iterable[T] | Iterable[dict]:
190+
def query_sync(
191+
self, query_string: str, into_type: Type[T] | None = None, error_handler: Callable[[bytes], None] | None = None
192+
) -> Iterable[T] | Iterable[dict]:
182193
"""
183194
Perform a synchronous query and return an iterable of results.
184195
185196
Args:
186197
query_string: The SQL query string to execute.
187198
into_type: Optional type to cast each row into.
188-
199+
error_handler: Optional function to handle errors in the response.
189200
Returns:
190201
An iterable of parsed rows as either dictionaries or instances of the specified type.
191202
"""
192-
data = self.parse_query_response(self._query_sync(query_string))
203+
query_response = self._query_sync(query_string)
204+
try:
205+
data = self.parse_query_response(query_response)
206+
except Exception as e:
207+
if error_handler:
208+
error_handler(query_response)
209+
raise e
193210

194211
return self.parse_and_yield_query_response(data, into_type)
195212

0 commit comments

Comments
 (0)