Skip to content

Commit 4c39fd2

Browse files
feat: add fetchone, fetchall, fetchval convenience methods to ConnectionPool
The pool had execute() and fetch() but not fetchone(), fetchall(), or fetchval(), forcing users to drop to acquire() for these operations. Add the three missing methods for API consistency with DqliteConnection, matching the pattern used by asyncpg's Pool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a07ea81 commit 4c39fd2

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/dqliteclient/pool.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,23 @@ async def fetch(self, sql: str, params: Sequence[Any] | None = None) -> list[dic
221221
async with self.acquire() as conn:
222222
return await conn.fetch(sql, params)
223223

224+
async def fetchone(
225+
self, sql: str, params: Sequence[Any] | None = None
226+
) -> dict[str, Any] | None:
227+
"""Execute a query and return the first result using a pooled connection."""
228+
async with self.acquire() as conn:
229+
return await conn.fetchone(sql, params)
230+
231+
async def fetchall(self, sql: str, params: Sequence[Any] | None = None) -> list[list[Any]]:
232+
"""Execute a query and return results as lists using a pooled connection."""
233+
async with self.acquire() as conn:
234+
return await conn.fetchall(sql, params)
235+
236+
async def fetchval(self, sql: str, params: Sequence[Any] | None = None) -> Any:
237+
"""Execute a query and return a single value using a pooled connection."""
238+
async with self.acquire() as conn:
239+
return await conn.fetchval(sql, params)
240+
224241
async def close(self) -> None:
225242
"""Close the pool and all idle connections.
226243

tests/test_pool.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,3 +817,36 @@ async def test_fetch_through_pool(self, mock_connection: MagicMock) -> None:
817817
assert result == [{"id": 1}]
818818

819819
await pool.close()
820+
821+
async def test_fetchone_through_pool(self, mock_connection: MagicMock) -> None:
822+
mock_connection.fetchone = AsyncMock(return_value={"id": 1})
823+
pool = ConnectionPool(["localhost:9001"])
824+
825+
with patch.object(pool._cluster, "connect", return_value=mock_connection):
826+
await pool.initialize()
827+
result = await pool.fetchone("SELECT * FROM t LIMIT 1")
828+
assert result == {"id": 1}
829+
830+
await pool.close()
831+
832+
async def test_fetchall_through_pool(self, mock_connection: MagicMock) -> None:
833+
mock_connection.fetchall = AsyncMock(return_value=[[1, "a"], [2, "b"]])
834+
pool = ConnectionPool(["localhost:9001"])
835+
836+
with patch.object(pool._cluster, "connect", return_value=mock_connection):
837+
await pool.initialize()
838+
result = await pool.fetchall("SELECT * FROM t")
839+
assert result == [[1, "a"], [2, "b"]]
840+
841+
await pool.close()
842+
843+
async def test_fetchval_through_pool(self, mock_connection: MagicMock) -> None:
844+
mock_connection.fetchval = AsyncMock(return_value=42)
845+
pool = ConnectionPool(["localhost:9001"])
846+
847+
with patch.object(pool._cluster, "connect", return_value=mock_connection):
848+
await pool.initialize()
849+
result = await pool.fetchval("SELECT count(*) FROM t")
850+
assert result == 42
851+
852+
await pool.close()

0 commit comments

Comments
 (0)