- You can disable the use of prepared statements on a connection by setting
its `~Connection.prepare_threshold` attribute to `!None`.
+.. versionchanged:: 3.1
+ You can set `!prepare_threshold` as a `~Connection.connect()` keyword
+ parameter too.
+
.. seealso::
The `PREPARE`__ PostgreSQL documentation contains plenty of details about
ones exposed by :pq:`PQsendPrepare`, :pq:`PQsendQueryPrepared`.
.. __: https://www.postgresql.org/docs/current/sql-prepare.html
+
+.. warning::
+
+ Using external connection poolers, such as PgBouncer, is not compatible
+ with prepared statements, because the same client connection may change
+ the server session it refers to. If such middleware is used you should
+ disable connection pooling, by setting the `Connection.prepare_threshold`
+ attribute to `!None`.
to create fetching data (default:
`~psycopg.rows.tuple_row()`). See
:ref:`row-factories` for details.
+ :param prepare_threshold: Set the `prepare_threshold` attribute of the
+ connection.
More specialized use:
.. __: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
.. __: https://www.postgresql.org/docs/current/libpq-envars.html
+ .. versionchanged:: 3.1
+ Added *prepare_threshold* parameter.
+
.. automethod:: close
.. note::
------------------------
- Add :ref:`Two-Phase Commit <two-phase-commit>` support (:ticket:`#72`).
-- Add `pq.PGconn.trace()` and related trace functions (:ticket:`#167`).
- Return results from all queries run through `~Cursor.executemany()`; each
result set can be accessed by calling `~Cursor.nextset()` (:ticket:`#164`).
+- Add `pq.PGconn.trace()` and related trace functions (:ticket:`#167`).
+- Add *prepare_threshold* parameter to `Connection` init (:ticket:`#200`).
Current release
*,
autocommit: bool = False,
row_factory: RowFactory[Row],
+ prepare_threshold: Optional[int] = 5,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "Connection[Row]":
conninfo: str = "",
*,
autocommit: bool = False,
+ prepare_threshold: Optional[int] = 5,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "Connection[TupleRow]":
conninfo: str = "",
*,
autocommit: bool = False,
+ prepare_threshold: Optional[int] = 5,
row_factory: Optional[RowFactory[Row]] = None,
context: Optional[AdaptContext] = None,
**kwargs: Any,
rv.row_factory = row_factory
if context:
rv._adapters = AdaptersMap(context.adapters)
+ rv.prepare_threshold = prepare_threshold
return rv
def __enter__(self) -> "Connection[Row]":
conninfo: str = "",
*,
autocommit: bool = False,
+ prepare_threshold: Optional[int] = 5,
row_factory: AsyncRowFactory[Row],
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
conninfo: str = "",
*,
autocommit: bool = False,
+ prepare_threshold: Optional[int] = 5,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "AsyncConnection[TupleRow]":
conninfo: str = "",
*,
autocommit: bool = False,
+ prepare_threshold: Optional[int] = 5,
context: Optional[AdaptContext] = None,
row_factory: Optional[AsyncRowFactory[Row]] = None,
**kwargs: Any,
rv.row_factory = row_factory
if context:
rv._adapters = AdaptersMap(context.adapters)
+ rv.prepare_threshold = prepare_threshold
return rv
async def __aenter__(self) -> "AsyncConnection[Row]":
import pytest
+import psycopg
+
+
+@pytest.mark.parametrize("value", [None, 0, 3])
+def test_prepare_threshold_init(dsn, value):
+ with psycopg.connect(dsn, prepare_threshold=value) as conn:
+ assert conn.prepare_threshold == value
+
def test_dont_prepare(conn):
cur = conn.cursor()
import pytest
+import psycopg
+
pytestmark = pytest.mark.asyncio
+@pytest.mark.parametrize("value", [None, 0, 3])
+async def test_prepare_threshold_init(dsn, value):
+ async with await psycopg.AsyncConnection.connect(
+ dsn, prepare_threshold=value
+ ) as conn:
+ assert conn.prepare_threshold == value
+
+
async def test_dont_prepare(aconn):
cur = aconn.cursor()
for i in range(10):