Skip to content

Regression: Postgres' limit on bind parameters is u16::MAX, not i16::MAX #3464

@abonander

Description

@abonander

In #3441 I added this bit of code to silence the clippy::cast_possible_truncation warning:

let num_params = i16::try_from(arguments.len()).map_err(|_| {
err_protocol!(
"PgConnection::run(): too many arguments for query: {}",
arguments.len()
)
})?;

This will error if arguments.len() > 32767 (2^15 - 1).

We had modeled Bind::num_params as i16 so without any other context, this made sense: https://github.com/launchbadge/sqlx/blob/main/sqlx-postgres/src/message/bind.rs#L24

And this seems to be supported by the documentation which gives the field type as Int16: https://www.postgresql.org/docs/current/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-BIND

However, a key piece of information I had forgotten was that whether an integer is interpreted as signed or unsigned is context-dependent! And in fact, Postgres interprets this Int16 as unsigned, meaning the max number of parameters supported is actually 65535 (2^16 - 1). This is confirmed by Appendix K of the manual: https://www.postgresql.org/docs/current/limits.html

A quick, easy and correct fix would be to just change num_params to u16, but I think this should also be clarified in Postgres' docs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions