- Notifications
You must be signed in to change notification settings - Fork 435
Description
We are using asyncpg with pgbouncer statement pooling mode. According to the FAQ https://magicstack.github.io/asyncpg/current/faq.html#why-am-i-getting-prepared-statement-errors , setting statement_cache_size=0 will be enough to disable the usage of named prepared statement. But we are still getting the error prepared statement “__asyncpg_stmt_xx__” already exists.
After some exploration, we find that copy_records_to_table is calling self._prepare with name=None, which eventually instructs self._get_statement to create a named prepared statement. As a result, a named prepared statement will be created with name __asyncpg_stmt_xx__, and other client application using asyncpg could try to create something with the same name, leading to the error.
The fix would be straightforward if I am not missing anything: #1218
Test set up:
- asyncpg 0.30.0
- pgbouncer 1.22.0
- postgres 16.6
Simple script to reproduce:
import asyncpg import asyncio from asyncpg.connection import Connection async def main(): conn: Connection = await asyncpg.connect( host='localhost', port=6432, user='postgres', database='postgres', statement_cache_size=0, server_settings={'application_name': 'reproduce'} ) try: # Create a sample table await conn.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER, name TEXT, email TEXT ) ''') # Sample records to copy records = [ (1, 'Alice', 'alice@example.com'), (2, 'Bob', 'bob@example.com'), (3, 'Charlie', 'charlie@example.com') ] # Copy records to the table result = await conn.copy_records_to_table( 'users', records=records, columns=('id', 'name', 'email') ) print(f"Copy operation completed: {result}") finally: await conn.close() asyncio.run(main())