mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-19 16:44:07 +00:00
fix(postgres): max number of binds is 65535, not 32767 (regression)
This commit is contained in:
@@ -204,7 +204,12 @@ impl PgConnection {
|
||||
|
||||
let format = if let Some(mut arguments) = arguments {
|
||||
// Check this before we write anything to the stream.
|
||||
let num_params = i16::try_from(arguments.len()).map_err(|_| {
|
||||
//
|
||||
// Note: Postgres actually interprets this value as unsigned,
|
||||
// making the max number of parameters 65535, not 32767
|
||||
// https://github.com/launchbadge/sqlx/issues/3464
|
||||
// https://www.postgresql.org/docs/current/limits.html
|
||||
let num_params = u16::try_from(arguments.len()).map_err(|_| {
|
||||
err_protocol!(
|
||||
"PgConnection::run(): too many arguments for query: {}",
|
||||
arguments.len()
|
||||
|
||||
@@ -3,6 +3,12 @@ use crate::message::{FrontendMessage, FrontendMessageFormat};
|
||||
use crate::PgValueFormat;
|
||||
use std::num::Saturating;
|
||||
|
||||
/// <https://www.postgresql.org/docs/current/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-BIND>
|
||||
///
|
||||
/// ## Note:
|
||||
///
|
||||
/// The integer values for number of bind parameters, number of parameter format codes,
|
||||
/// and number of result format codes all are interpreted as *unsigned*!
|
||||
#[derive(Debug)]
|
||||
pub struct Bind<'a> {
|
||||
/// The ID of the destination portal (`PortalId::UNNAMED` selects the unnamed portal).
|
||||
@@ -18,10 +24,11 @@ pub struct Bind<'a> {
|
||||
/// parameters; or it can equal the actual number of parameters.
|
||||
pub formats: &'a [PgValueFormat],
|
||||
|
||||
// Note: interpreted as unsigned, as is `formats.len()` and `result_formats.len()`
|
||||
/// The number of parameters.
|
||||
///
|
||||
/// May be different from `formats.len()`
|
||||
pub num_params: i16,
|
||||
pub num_params: u16,
|
||||
|
||||
/// The value of each parameter, in the indicated format.
|
||||
pub params: &'a [u8],
|
||||
@@ -64,7 +71,11 @@ impl FrontendMessage for Bind<'_> {
|
||||
|
||||
buf.put_statement_name(self.statement);
|
||||
|
||||
let formats_len = i16::try_from(self.formats.len()).map_err(|_| {
|
||||
// NOTE: the integer values for the number of parameters and format codes in this message
|
||||
// are all interpreted as *unsigned*!
|
||||
//
|
||||
// https://github.com/launchbadge/sqlx/issues/3464
|
||||
let formats_len = u16::try_from(self.formats.len()).map_err(|_| {
|
||||
err_protocol!("too many parameter format codes ({})", self.formats.len())
|
||||
})?;
|
||||
|
||||
@@ -78,7 +89,7 @@ impl FrontendMessage for Bind<'_> {
|
||||
|
||||
buf.extend(self.params);
|
||||
|
||||
let result_formats_len = i16::try_from(self.formats.len())
|
||||
let result_formats_len = u16::try_from(self.formats.len())
|
||||
.map_err(|_| err_protocol!("too many result format codes ({})", self.formats.len()))?;
|
||||
|
||||
buf.extend(result_formats_len.to_be_bytes());
|
||||
|
||||
@@ -14,6 +14,8 @@ impl BackendMessage for ParameterDescription {
|
||||
const FORMAT: BackendMessageFormat = BackendMessageFormat::ParameterDescription;
|
||||
|
||||
fn decode_body(mut buf: Bytes) -> Result<Self, Error> {
|
||||
// Note: this is correct, max parameters is 65535, not 32767
|
||||
// https://github.com/launchbadge/sqlx/issues/3464
|
||||
let cnt = buf.get_u16();
|
||||
let mut types = SmallVec::with_capacity(cnt as usize);
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ impl FrontendMessage for Parse<'_> {
|
||||
|
||||
buf.put_str_nul(self.query);
|
||||
|
||||
let param_types_len = i16::try_from(self.param_types.len()).map_err(|_| {
|
||||
// Note: actually interpreted as unsigned
|
||||
// https://github.com/launchbadge/sqlx/issues/3464
|
||||
let param_types_len = u16::try_from(self.param_types.len()).map_err(|_| {
|
||||
err_protocol!(
|
||||
"param_types.len() too large for binary protocol: {}",
|
||||
self.param_types.len()
|
||||
|
||||
Reference in New Issue
Block a user