mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 06:24:16 +00:00
doc(sqlite): cover lack of NUMERIC
support (#2890)
This commit is contained in:
parent
d3a28d461f
commit
ed1b030e91
1 changed files with 51 additions and 0 deletions
|
@ -79,6 +79,57 @@
|
|||
//! In addition, `Option<T>` is supported where `T` implements `Type`. An `Option<T>` represents
|
||||
//! a potentially `NULL` value from SQLite.
|
||||
//!
|
||||
//! # Non-feature: `NUMERIC` / `rust_decimal` / `bigdecimal` Support
|
||||
//! Support for mapping `rust_decimal::Decimal` and `bigdecimal::BigDecimal` to SQLite has been
|
||||
//! deliberately omitted because SQLite does not have native support for high-
|
||||
//! or arbitrary-precision decimal arithmetic, and to pretend so otherwise would be a
|
||||
//! significant misstep in API design.
|
||||
//!
|
||||
//! The in-tree [`decimal.c`] extension is unfortunately not included in the [amalgamation],
|
||||
//! which is used to build the bundled version of SQLite3 for `libsqlite3-sys` (which we have
|
||||
//! enabled by default for the simpler setup experience), otherwise we could support that.
|
||||
//!
|
||||
//! The `NUMERIC` type affinity, while seemingly designed for storing decimal values,
|
||||
//! stores non-integer real numbers as double-precision IEEE-754 floating point,
|
||||
//! i.e. `REAL` in SQLite, `f64` in Rust, `double` in C/C++, etc.
|
||||
//!
|
||||
//! [Datatypes in SQLite: Type Affinity][type-affinity] (accessed 2023/11/20):
|
||||
//!
|
||||
//! > A column with NUMERIC affinity may contain values using all five storage classes.
|
||||
//! When text data is inserted into a NUMERIC column, the storage class of the text is converted to
|
||||
//! INTEGER or REAL (in order of preference) if the text is a well-formed integer or real literal,
|
||||
//! respectively. If the TEXT value is a well-formed integer literal that is too large to fit in a
|
||||
//! 64-bit signed integer, it is converted to REAL. For conversions between TEXT and REAL storage
|
||||
//! classes, only the first 15 significant decimal digits of the number are preserved.
|
||||
//!
|
||||
//! With the SQLite3 interactive CLI, we can see that a higher-precision value
|
||||
//! (20 digits in this case) is rounded off:
|
||||
//!
|
||||
//! ```text
|
||||
//! sqlite> CREATE TABLE foo(bar NUMERIC);
|
||||
//! sqlite> INSERT INTO foo(bar) VALUES('1.2345678901234567890');
|
||||
//! sqlite> SELECT * FROM foo;
|
||||
//! 1.23456789012346
|
||||
//! ```
|
||||
//!
|
||||
//! It appears the `TEXT` storage class is only used if the value contains invalid characters
|
||||
//! or extra whitespace.
|
||||
//!
|
||||
//! Thus, the `NUMERIC` type affinity is **unsuitable** for storage of high-precision decimal values
|
||||
//! and should be **avoided at all costs**.
|
||||
//!
|
||||
//! Support for `rust_decimal` and `bigdecimal` would only be a trap because users will naturally
|
||||
//! want to use the `NUMERIC` type affinity, and might otherwise encounter serious bugs caused by
|
||||
//! rounding errors that they were deliberately avoiding when they chose an arbitrary-precision type
|
||||
//! over a floating-point type in the first place.
|
||||
//!
|
||||
//! Instead, you should only use a type affinity that SQLite will not attempt to convert implicitly,
|
||||
//! such as `TEXT` or `BLOB`, and map values to/from SQLite as strings.
|
||||
//!
|
||||
//! [`decimal.c`]: https://www.sqlite.org/floatingpoint.html#the_decimal_c_extension
|
||||
//! [amalgamation]: https://www.sqlite.org/amalgamation.html
|
||||
//! [type-affinity]: https://www.sqlite.org/datatype3.html#type_affinity
|
||||
//!
|
||||
|
||||
pub(crate) use sqlx_core::types::*;
|
||||
|
||||
|
|
Loading…
Reference in a new issue