.. __: https://www.postgresql.org/docs/current/sql-prepare.html
+
+.. _pgbouncer:
+
+Using prepared statements with PgBouncer
+----------------------------------------
+
.. warning::
Unless a connection pooling middleware explicitly declares otherwise, they
is used you should disable prepared statements, by setting the
`Connection.prepare_threshold` attribute to `!None`.
-
-.. _pgbouncer:
-
-Using prepared statements with PgBouncer
-----------------------------------------
-
Starting from 3.2, Psycopg supports prepared statements when using the
PgBouncer__ middleware, using the following caveats:
If libpq 17 is not available on your client, but PgBouncer is 1.22 or
higher, you can still use Psycopg *as long as you disable deallocation*.
- You can do so by setting `Connection.prepared_max` to `!sys.maxsize`.
+ You can do so by setting `Connection.prepared_max` to `!None`.
If more queries need to be prepared, old ones are deallocated__.
+ Specifying `!None` can be useful for middleware that don't support
+ deallocation; see :ref:`prepared statements notes <pgbouncer>`.
+
.. __: https://www.postgresql.org/docs/current/sql-deallocate.html
+ .. versionchanged:: 3.2
+
+ Added support for the `!None` value.
+
.. rubric:: Methods you can use to do something cool
# Copyright (C) 2020 The Psycopg Team
+import sys
import logging
from typing import Callable, Generic
from typing import List, NamedTuple, Optional, Tuple, Union
self._prepared.prepare_threshold = value
@property
- def prepared_max(self) -> int:
+ def prepared_max(self) -> Optional[int]:
"""
Maximum number of prepared statements on the connection.
- Default value: 100
+ `!None` means no max number of prepared statements. The default value
+ is 100.
"""
- return self._prepared.prepared_max
+ rv = self._prepared.prepared_max
+ return rv if rv != sys.maxsize else None
@prepared_max.setter
- def prepared_max(self, value: int) -> None:
+ def prepared_max(self, value: Optional[int]) -> None:
+ if value is None:
+ value = sys.maxsize
self._prepared.prepared_max = value
# Generators to perform high-level operations on the connection
Prepared statements tests
"""
+import sys
import logging
import datetime as dt
from decimal import Decimal
assert "DEALLOCATE" in msgs
+def test_prepared_max_none(conn):
+ conn.prepared_max = 42
+ assert conn.prepared_max == 42
+ assert conn._prepared.prepared_max == 42
+
+ conn.prepared_max = None
+ assert conn._prepared.prepared_max == sys.maxsize
+ assert conn.prepared_max is None
+
+ conn.prepared_max = 0
+ assert conn._prepared.prepared_max == 0
+ assert conn.prepared_max == 0
+
+ conn.prepared_max = 24
+ assert conn.prepared_max == 24
+ assert conn._prepared.prepared_max == 24
+
+
def test_different_types(conn):
conn.prepare_threshold = 0
conn.execute("select %s", [None])