Skip to content

fix(any): rewrite ? placeholders to $N for Postgres backend (#3000)#4351

Open
allocsys wants to merge 1 commit into
transact-rs:mainfrom
allocsys:fix/any-postgres-placeholder-3000-squashed
Open

fix(any): rewrite ? placeholders to $N for Postgres backend (#3000)#4351
allocsys wants to merge 1 commit into
transact-rs:mainfrom
allocsys:fix/any-postgres-placeholder-3000-squashed

Conversation

@allocsys

Copy link
Copy Markdown

Fixes #3000.

The Any driver always wrote ?-style placeholders, which is correct for MySQL/SQLite but not Postgres ($1, $2, ...). This caused a syntax error on any query issued through Any + Postgres that had more than a trivial shape (e.g. bound params combined with LIMIT/OFFSET).

The originally proposed fix (adding an AnyKind field to AnyArguments plus a format_placeholder override) doesn't work: QueryBuilder<Any>::push_bind() writes placeholders into the SQL string before any backend is known, since AnyArguments is built via Default::default(). The backend is only resolved later, in AnyConnectionBackend::fetch_many().

This PR instead rewrites ? -> $1, $2, ... inside sqlx-postgres/src/any.rs, right before the query is dispatched to PgConnection (covers fetch_many, fetch_optional, prepare_with, and describe). Only the Postgres leg needs this, since MySQL/SQLite already use ? natively.

The rewrite is SQL-aware (not a blind str::replace) so it skips ? that appears inside:

  • single-quoted string literals (with '' escaping)
  • double-quoted identifiers (with "" escaping)
  • dollar-quoted blocks ($$...$$ and $tag$...$tag$)
  • -- line comments and /* */ block comments

Added unit tests covering the placeholder-numbering happy path and each of the above edge cases.

CI (Examples, SQLx, SQLx CLI) passes clean on the fork: allocsys#1.

…-rs#3000)

QueryBuilder<Any>::push_bind() always writes '?' placeholders since
AnyArguments has no backend context at build time. This adds a
SQL-aware rewrite (skipping string literals, quoted identifiers,
dollar-quoted strings, and comments) applied on the Postgres leg of
the Any driver, right before the query hits the wire protocol in
fetch_many/fetch_optional/prepare_with/describe.

MySQL and SQLite are unaffected since they already use '?' natively.

Fixes transact-rs#3000
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.

Bad query argument format for postgres with Any driver

1 participant