Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IEEE 754 to Postgres compatibility page #3185

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions docs/sql/data_types/numeric.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,26 @@ For more complex mathematical operations, however, floating-point arithmetic is
In general, we advise that:

* If you require exact storage of numbers with a known number of decimal digits and require exact additions, subtractions, and multiplications (such as for monetary amounts), use the [`DECIMAL` data type](#fixed-point-decimals) or its `NUMERIC` alias instead.
* If you want to do fast or complicated calculations, the floating-point data types may be more appropriate. However, if you use the results for anything important, you should evaluate your implementation carefully for corner cases (ranges, infinities, underflows, invalid operations) that may be handled differently from what you expect and you should familiarize yourself with common floating-point pitfalls. The article ["What Every Computer Scientist Should Know About
Floating-Point Arithmetic" by David Goldberg](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) and [the floating point series on Bruce Dawson's blog](https://randomascii.wordpress.com/2017/06/19/sometimes-floating-point-math-is-perfect/) provide excellent starting points.
* If you want to do fast or complicated calculations, the floating-point data types may be more appropriate. However, if you use the results for anything important, you should evaluate your implementation carefully for corner cases (ranges, infinities, underflows, invalid operations) that may be handled differently from what you expect and you should familiarize yourself with common floating-point pitfalls. The article ["What Every Computer Scientist Should Know About Floating-Point Arithmetic" by David Goldberg](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) and [the floating point series on Bruce Dawson's blog](https://randomascii.wordpress.com/2017/06/19/sometimes-floating-point-math-is-perfect/) provide excellent starting points.

On most platforms, the `REAL` type has a range of at least 1E-37 to 1E+37 with a precision of at least 6 decimal digits. The `DOUBLE` type typically has a range of around 1E-307 to 1E+308 with a precision of at least 15 digits. Positive numbers outside of these ranges (and negative numbers ourside the mirrored ranges) may cause errors on some platforms but will usually be converted to zero or infinity, respectively.

In addition to ordinary numeric values, the floating-point types have several special values:
In addition to ordinary numeric values, the floating-point types have several special values representing IEEE 754 special values:

* `Infinity`
* `-Infinity`
* `NaN`
* `Infinity`: infinity
* `-Infinity`: negative infinity
* `NaN`: not a number

These represent the IEEE 754 special values "infinity", "negative infinity", and "not-a-number", respectively. (On a machine whose floating-point arithmetic does not follow IEEE 754, these values will probably not work as expected.) When writing these values as constants in a SQL command, you must put quotes around them, for example: `UPDATE table SET x = '-Infinity'`. On input, these strings are recognized in a case-insensitive manner.
> On a machine whose floating-point arithmetic does not follow IEEE 754, these values will probably not work as expected.

When writing these values as constants in a SQL command, you must put quotes around them, for example:

```sql
UPDATE table
SET x = '-Infinity';
```

On input, these strings are recognized in a case-insensitive manner.

## Universally Unique Identifiers (`UUID`s)

Expand Down
55 changes: 41 additions & 14 deletions docs/sql/postgresql_compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,34 @@ title: PostgreSQL Compatibility
DuckDB's SQL dialect closely follows the conventions of the PostgreSQL dialect.
The few exceptions to this are listed on this page.

## Floating-Point Arithmetic

DuckDB and PostgreSQL handle floating-point arithmetic differently for division by zero. Neither system confirm the [IEEE Standard for Floating-Point Arithmetic (IEEE 754)](https://en.wikipedia.org/wiki/IEEE_754).
On operations involving infinity values, DuckDB and PostgreSQL align with each other but again they both deviate from IEEE 754.
To show the differences, run the following SQL queries:

```sql
SELECT 1.0 / 0.0 AS x;
SELECT 0.0 / 0.0 AS x;
SELECT -1.0 / 0.0 AS x;
SELECT 'Infinity'::FLOAT / 'Infinity'::FLOAT AS x;
SELECT 1.0 / 'Infinity'::FLOAT AS x;
SELECT 'Infinity'::FLOAT - 'Infinity'::FLOAT AS x;
SELECT 'Infinity'::FLOAT - 1.0 AS x;
```

<div class="narrow_table monospace_table"></div>

| Expression | DuckDB | PostgreSQL | IEEE 754 |
| :---------------------- | -------: | ---------: | --------: |
| 1.0 / 0.0 | NULL | error | Infinity |
| 0.0 / 0.0 | NULL | error | Nan |
| -1.0 / 0.0 | NULL | error | -Infinity |
| 'Infinity' / 'Infinity' | NaN | NaN | NaN |
| 1.0 / 'Infinity' | 0.0 | 0.0 | 0.0 |
| 'Infinity' - 'Infinity' | NaN | NaN | NaN |
| 'Infinity' - 1.0 | Infinity | Infinity | Infinity |

## Division on Integers

When computing division on integers, PostgreSQL performs integer divison, while DuckDB performs float division:
Expand All @@ -25,19 +53,19 @@ PostgreSQL returns:

DuckDB returns:

| x |
|----:|
| 0.5 |
| x |
| ---: |
| 0.5 |

To perform integer division in DuckDB, use the `//` operator:

```sql
SELECT 1 // 2 AS x;
```

| x |
|--:|
| 0 |
| x |
| ---: |
| 0 |

## `UNION` of Boolean and Integer Values

Expand All @@ -57,10 +85,10 @@ ERROR: UNION types boolean and integer cannot be matched

DuckDB performs an enforced cast, therefore, it completes the query and returns the following:

| x |
|--:|
| 1 |
| 2 |
| x |
| ---: |
| 1 |
| 2 |

## Case Sensitivity for Quoted Identifiers

Expand Down Expand Up @@ -103,12 +131,11 @@ SELECT table_name FROM duckdb_tables();

<div class="narrow_table monospace_table"></div>

| table_name |
|---------------|
| table_name |
| ------------- |
| MyTaBLe |
| PreservedCase |


PostgreSQL's behavior of lowercasing identifiers is accessible using the [`preserve_identifier_case` option]({% link docs/configuration/overview.md %}#local-configuration-options):

```sql
Expand All @@ -120,7 +147,7 @@ SELECT table_name FROM duckdb_tables();
<div class="narrow_table monospace_table"></div>

| table_name |
|------------|
| ---------- |
| mytable |

However, the case insensitive matching in the system for identifiers cannot be turned off.
Loading