Skip to content

Commit

Permalink
feat(postgres): make extra_float_digits settable (#1774)
Browse files Browse the repository at this point in the history
  • Loading branch information
abonander authored Apr 1, 2022
1 parent c30a4a5 commit f858138
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
7 changes: 4 additions & 3 deletions sqlx-core/src/postgres/connection/establish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ impl PgConnection {
("client_encoding", "UTF8"),
// Sets the time zone for displaying and interpreting time stamps.
("TimeZone", "UTC"),
// Adjust postgres to return precise values for floats
// NOTE: This is default in postgres 12+
("extra_float_digits", "3"),
];

if let Some(ref extra_float_digits) = options.extra_float_digits {
params.push(("extra_float_digits", extra_float_digits));
}

if let Some(ref application_name) = options.application_name {
params.push(("application_name", application_name));
}
Expand Down
56 changes: 56 additions & 0 deletions sqlx-core/src/postgres/options/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::env::var;
use std::fmt::{Display, Write};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -87,6 +88,7 @@ pub struct PgConnectOptions {
pub(crate) statement_cache_capacity: usize,
pub(crate) application_name: Option<String>,
pub(crate) log_settings: LogSettings,
pub(crate) extra_float_digits: Option<Cow<'static, str>>,
pub(crate) options: Option<String>,
}

Expand Down Expand Up @@ -147,6 +149,7 @@ impl PgConnectOptions {
.unwrap_or_default(),
statement_cache_capacity: 100,
application_name: var("PGAPPNAME").ok(),
extra_float_digits: Some("3".into()),
log_settings: Default::default(),
options: var("PGOPTIONS").ok(),
}
Expand Down Expand Up @@ -336,6 +339,59 @@ impl PgConnectOptions {
self
}

/// Sets or removes the `extra_float_digits` connection option.
///
/// This changes the default precision of floating-point values returned in text mode (when
/// not using prepared statements such as calling methods of [`Executor`] directly).
///
/// Historically, Postgres would by default round floating-point values to 6 and 15 digits
/// for `float4`/`REAL` (`f32`) and `float8`/`DOUBLE` (`f64`), respectively, which would mean
/// that the returned value may not be exactly the same as its representation in Postgres.
///
/// The nominal range for this value is `-15` to `3`, where negative values for this option
/// cause floating-points to be rounded to that many fewer digits than normal (`-1` causes
/// `float4` to be rounded to 5 digits instead of six, or 14 instead of 15 for `float8`),
/// positive values cause Postgres to emit that many extra digits of precision over default
/// (or simply use maximum precision in Postgres 12 and later),
/// and 0 means keep the default behavior (or the "old" behavior described above
/// as of Postgres 12).
///
/// SQLx sets this value to 3 by default, which tells Postgres to return floating-point values
/// at their maximum precision in the hope that the parsed value will be identical to its
/// counterpart in Postgres. This is also the default in Postgres 12 and later anyway.
///
/// However, older versions of Postgres and alternative implementations that talk the Postgres
/// protocol may not support this option, or the full range of values.
///
/// If you get an error like "unknown option `extra_float_digits`" when connecting, try
/// setting this to `None` or consult the manual of your database for the allowed range
/// of values.
///
/// For more information, see:
/// * [Postgres manual, 20.11.2: Client Connection Defaults; Locale and Formatting][20.11.2]
/// * [Postgres manual, 8.1.3: Numeric Types; Floating-point Types][8.1.3]
///
/// [`Executor`]: crate::executor::Executor
/// [20.11.2]: https://www.postgresql.org/docs/current/runtime-config-client.html#RUNTIME-CONFIG-CLIENT-FORMAT
/// [8.1.3]: https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-FLOAT
///
/// ### Examples
/// ```rust
/// # use sqlx_core::postgres::PgConnectOptions;
///
/// let mut options = PgConnectOptions::new()
/// // for Redshift and Postgres 10
/// .extra_float_digits(2);
///
/// let mut options = PgConnectOptions::new()
/// // don't send the option at all (Postgres 9 and older)
/// .extra_float_digits(None);
/// ```
pub fn extra_float_digits(mut self, extra_float_digits: impl Into<Option<i8>>) -> Self {
self.extra_float_digits = extra_float_digits.into().map(|it| it.to_string().into());
self
}

/// Set additional startup options for the connection as a list of key-value pairs.
///
/// # Example
Expand Down

0 comments on commit f858138

Please sign in to comment.