Skip to content

Commit 5abcb28

Browse files
committed
Cache C-API prepared statements for repeated parameterized execute() calls
The pybind path was already patched with _get_or_prepare_pybind_statement to reuse prepared statements for repeated parameterized execute() calls, preventing unbounded memory growth (RSS raising). The C-API execute() path had the same bug: every parameterized execute() with a string query created a new PreparedStatement via self._prepare(), which called self._connection.prepare() on the C-API module — never reusing previously prepared statements. Add _get_or_prepare_capi_statement() that caches PreparedStatement objects keyed by the normalized query string in the same _pybind_implicit_prepared_cache dict (already cleared on close). The else branch now delegates to this cache instead of calling self._prepare() directly.
1 parent 7d514fa commit 5abcb28

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

src_py/connection.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,18 @@ def _get_or_prepare_pybind_statement(
479479
self._pybind_implicit_prepared_cache[query] = prepared
480480
return prepared
481481

482+
def _get_or_prepare_capi_statement(
483+
self,
484+
query: str,
485+
parameters: dict[str, Any],
486+
) -> PreparedStatement:
487+
cached = self._pybind_implicit_prepared_cache.get(query)
488+
if cached is not None:
489+
return cached
490+
prepared = self._prepare(query, parameters)
491+
self._pybind_implicit_prepared_cache[query] = prepared
492+
return prepared
493+
482494
def _maybe_raise_scan_unsupported_object(self, query: str) -> None:
483495
match = re.search(
484496
r"\bLOAD\s+FROM\s+([A-Za-z_][A-Za-z0-9_]*)\b", query, re.IGNORECASE
@@ -582,7 +594,9 @@ def execute(
582594
query, parameters
583595
)
584596
prepared_statement = (
585-
self._prepare(query, parameters) if isinstance(query, str) else query
597+
self._get_or_prepare_capi_statement(query, parameters)
598+
if isinstance(query, str)
599+
else query
586600
)
587601
query_result_internal = self._connection.execute(
588602
prepared_statement._prepared_statement, parameters

0 commit comments

Comments
 (0)