From e13cc9954392521ec4c9d0d01a96e3f3a1ecaa40 Mon Sep 17 00:00:00 2001 From: Peter Adams <18162810+Maxteabag@users.noreply.github.com> Date: Wed, 5 Aug 2026 19:32:07 +0200 Subject: [PATCH] fix(oracle): cap fetch buffers to result limit --- .../connections/providers/oracle/adapter.py | 7 +++--- .../oracle/test_statement_execution.py | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/sqlit/domains/connections/providers/oracle/adapter.py b/sqlit/domains/connections/providers/oracle/adapter.py index d295a1ec..92e00232 100644 --- a/sqlit/domains/connections/providers/oracle/adapter.py +++ b/sqlit/domains/connections/providers/oracle/adapter.py @@ -384,9 +384,10 @@ def execute_query(self, conn: Any, query: str, max_rows: int | None = None) -> t cursor = conn.cursor() try: # Larger fetch batches cut per-round-trip overhead on high-latency - # links (oracledb defaults: arraysize=100, prefetchrows=2). - cursor.arraysize = 1000 - cursor.prefetchrows = 1001 + # links without fetching beyond the requested result cap. + row_budget = max_rows + 1 if max_rows is not None else 1001 + cursor.arraysize = min(1000, max(1, row_budget)) + cursor.prefetchrows = min(1001, max(1, row_budget)) cursor.execute(_prepare_statement(query)) if cursor.description: columns = [col[0] for col in cursor.description] diff --git a/tests/connections/providers/oracle/test_statement_execution.py b/tests/connections/providers/oracle/test_statement_execution.py index 73eda739..1b8a886e 100644 --- a/tests/connections/providers/oracle/test_statement_execution.py +++ b/tests/connections/providers/oracle/test_statement_execution.py @@ -43,6 +43,30 @@ def test_execute_query_removes_sql_statement_terminator( mock_conn.cursor.return_value.execute.assert_called_once_with(expected) +@pytest.mark.parametrize( + ("max_rows", "expected_arraysize", "expected_prefetchrows"), + [ + (None, 1000, 1001), + (1, 2, 2), + (999, 1000, 1000), + (1000, 1000, 1001), + ], +) +def test_execute_query_caps_fetch_buffers_to_requested_rows( + adapter: OracleAdapter, + mock_conn: MagicMock, + max_rows: int | None, + expected_arraysize: int, + expected_prefetchrows: int, +) -> None: + """Small result limits must not prefetch hundreds of discarded rows.""" + adapter.execute_query(mock_conn, "SELECT 1 FROM DUAL", max_rows=max_rows) + + cursor = mock_conn.cursor.return_value + assert cursor.arraysize == expected_arraysize + assert cursor.prefetchrows == expected_prefetchrows + + def test_execute_non_query_removes_sql_statement_terminator( adapter: OracleAdapter, mock_conn: MagicMock,