Skip to content

feat: add binary_parameters provider attribute for connection pooler compatibility#629

Open
MrrKirill wants to merge 3 commits into
cyrilgdn:mainfrom
MrrKirill:feat/binary-parameters
Open

feat: add binary_parameters provider attribute for connection pooler compatibility#629
MrrKirill wants to merge 3 commits into
cyrilgdn:mainfrom
MrrKirill:feat/binary-parameters

Conversation

@MrrKirill

@MrrKirill MrrKirill commented Apr 13, 2026

Copy link
Copy Markdown

Problem

When connecting to PostgreSQL through a connection pooler (PgBouncer, Odyssey, etc.) in TRANSACTION pooling mode, the provider fails with:

Error: could not check if database exists: pq: unnamed prepared statement does not exist

This happens because lib/pq uses the Extended Query Protocol (Parse → Bind → Execute) for parameterized queries. In TRANSACTION mode, the pooler may route Bind/Execute to a different backend process than the one that received Parse. The new backend has no knowledge of the parsed statement, causing the error.

This is a well-known limitation documented by:

  • lib/pq#889 — unnamed prepared statement does not exist
  • PgBouncer FAQ — prepared statements and transaction pooling

Solution

Add a new binary_parameters provider attribute that maps directly to the lib/pq connection parameter of the same name.

When enabled, lib/pq switches from Extended Query Protocol to Simple Query Protocol for parameterized queries — sending everything in a single message without creating prepared statements. This makes all provider operations compatible with TRANSACTION pooling mode.

Usage

provider "postgresql" {
  host              = "pgbouncer.example.com"
  port              = 6432
  binary_parameters = true  # avoids prepared statements
  # ...
}

Naming

The attribute is named binary_parameters to match the lib/pq DSN parameter name directly, following the project's established convention (e.g. sslmode matches lib/pq, while Terraform-style ssl_mode was deprecated).

Changes

  • postgresql/config.go: Add BinaryParameters bool field to Config struct; append binary_parameters=yes to connection params when enabled (only for postgres scheme, same as sslmode/connect_timeout)
  • postgresql/provider.go: Add binary_parameters schema attribute (TypeBool, optional, default false); wire it in providerConfigure()
  • postgresql/config_test.go: Add test cases verifying binary_parameters=yes appears in connection params when enabled, is absent when disabled, and is ignored for non-postgres schemes

Testing

Tested with Odyssey connection pooler:

Pooling Mode binary_parameters Operation Result
SESSION false apply + destroy
TRANSACTION false apply → destroy unnamed prepared statement does not exist
TRANSACTION true apply + destroy

Resources tested: postgresql_grant, postgresql_default_privileges, postgresql_schemas (data source).

Closes #191

…compatibility

When connecting through connection poolers (PgBouncer, Odyssey) in
TRANSACTION pooling mode, lib/pq's Extended Query Protocol causes
'unnamed prepared statement does not exist' errors.

Adding binary_parameters=yes to the connection string switches lib/pq
to Simple Query Protocol, avoiding prepared statements entirely.

New provider attribute:
  binary_parameters = true  (default: false)

Only applies to postgres scheme (not awspostgres/gcppostgres).

Closes cyrilgdn#191

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new binary_parameters provider configuration attribute to improve compatibility when the provider connects to PostgreSQL through transaction-pooling connection poolers (e.g., PgBouncer/Odyssey), by propagating binary_parameters=yes into the lib/pq connection parameters when enabled.

Changes:

  • Adds binary_parameters to the provider schema and wires it into provider configuration.
  • Extends connection string parameter generation to include binary_parameters=yes (for scheme = "postgres" only) when enabled.
  • Adds unit tests covering enabled/disabled behavior and non-postgres scheme behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
postgresql/provider.go Adds the binary_parameters schema attribute and passes it into Config during providerConfigure.
postgresql/config.go Adds BinaryParameters to Config and includes binary_parameters=yes in connParams() for the postgres scheme when enabled.
postgresql/config_test.go Adds test cases verifying parameter inclusion/exclusion and that non-postgres schemes ignore the setting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MrrKirill

MrrKirill commented Jul 17, 2026

Copy link
Copy Markdown
Author

Hi! I merged the latest main branch and ran additional local tests for this change.

The repository checks passed. I also ran the full provider acceptance suite against PostgreSQL 12 through 18, and all 14 suites passed.

Separately, I tested transaction pooling on PostgreSQL 18.4 with:

  • Odyssey 1.5.1
  • PgBouncer 1.25.2

With binary_parameters=false, the following error was repeatedly reproduced:

pq: unnamed prepared statement does not exist

With binary_parameters=true, both poolers successfully completed:

  • terraform apply
  • a no-change terraform plan
  • terraform destroy
  • SQL cleanup verification

This change should help users who currently cannot use the provider through transaction-pooling proxies.

@cyrilgdn, when you have time, I would appreciate another look at this PR. I am happy to make any additional changes needed before merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: binary_parameters

3 participants