Skip to content

Commit

Permalink
Add NaN support (pgspider#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkgrgis committed Aug 8, 2024
1 parent 09bb507 commit befdc6d
Show file tree
Hide file tree
Showing 22 changed files with 1,295 additions and 233 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Features
- `timestamp`: `text` and `int`,
- `uuid`: `text`(32..39) and `blob`(16),
- `bool`: `text`(1..5) and `int`,
- `double precision`, `float` and `numeric`: `real` values and special values with `text` affinity (`+Infinity` and `-Infinity`).
- `double precision`, `float` and `numeric`: `real` values and special values with `text` affinity (`+Infinity`, `-Infinity`, `NaN`).
- Support mixed SQLite [data affinity](https://www.sqlite.org/datatype3.html) output (`INSERT`/`UPDATE`) for such data types as
- `timestamp`: `text`(default) or `int`,
- `uuid`: `text`(36) or `blob`(16)(default).
Expand Down Expand Up @@ -593,7 +593,7 @@ Array support is experimental. Please be careful.
- SQLite promises to preserve the 15 most significant digits of a floating point value. The big value which exceed 15 most significant digits may become different value after inserted.
- SQLite does not support `numeric` type as PostgreSQL. Therefore, it does not allow to store numbers with too high precision and scale. Error out of range occurs.
- SQLite does not support `NaN` special value for IEEE 754-2008 numbers. Please use this special value very cerefully because there is no such conception in SQLite at all and `NaN` value treated in SQLite as `NULL`.
- SQLite support `+Infinity` and `-Infinity` special values for IEEE 754-2008 numbers in SQL expressions with numeric context. This values can be readed with both `text` and `real` affiniy, but can be writed to SQLite only with `real` affinity (as signed out of range value `9e999`).
- SQLite support `+Infinity` and `-Infinity` special values for IEEE 754-2008 numbers in SQL expressions with numeric context. This values can be readed with both `text` and `real` affiniy, but can be writed to SQLite only with `real` affinity (as signed out of range value `9.0e999`).

### Boolean values
- `sqlite_fdw` boolean values support exists only for `bool` columns in foreign table. SQLite documentation recommends to store boolean as value with `integer` [affinity](https://www.sqlite.org/datatype3.html). `NULL` isn't converted, 1 converted to `true`, all other `NOT NULL` values converted to `false`. During `SELECT ... WHERE condition_column` condition converted only to `condition_column`.
Expand Down
126 changes: 107 additions & 19 deletions expected/12.16/extra/float4.out
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,9 @@ INSERT INTO "type_FLOAT_INF" (i, f) VALUES (13, 'Inf');
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (14, '+Inf');
--Testcase 288:
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (15, '-Inf');
--Testcase 289: SQLite ignores NaN
--see https://github.com/sqlite/sqlite/blob/6db0b11e078f4b651f0cf00f845f3d77700c1a3a/src/vdbemem.c#L973
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (16, 'NaN');
--Testcase 290:
ALTER FOREIGN TABLE "type_FLOAT_INF" ALTER COLUMN "f" TYPE text;
--Testcase 291:
Expand All @@ -1255,7 +1258,7 @@ INSERT INTO "type_FLOAT_INF" (i, f) VALUES (21, '+Inf');
--Testcase 296:
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (22, '-Inf');
--Testcase 297:
--INSERT INTO "type_FLOAT_INF" (i, f) VALUES (23, 'NaN');
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (23, 'NaN');
--Testcase 298:
INSERT INTO "type_FLOAT_INF" (i, f) VALUES (24, 'Infinity__');
--Testcase 299:
Expand Down Expand Up @@ -1293,13 +1296,15 @@ SELECT * FROM "type_FLOAT_INF";
13 | Infinity
14 | Infinity
15 | -Infinity
16 |
17 | Infinity
18 | Infinity
19 | -Infinity
20 | Infinity
21 | Infinity
22 | -Infinity
(19 rows)
23 | NaN
(21 rows)

--Testcase 306:
SELECT * FROM "type_FLOAT_INF+";
Expand All @@ -1318,13 +1323,15 @@ SELECT * FROM "type_FLOAT_INF+";
13 | Infinity | real | 3
14 | Infinity | real | 3
15 | -Infinity | real | 4
16 | | null |
17 | Infinity | text | 8
18 | Infinity | text | 9
19 | -Infinity | text | 9
20 | Infinity | text | 3
21 | Infinity | text | 4
22 | -Infinity | text | 4
(19 rows)
23 | NaN | text | 3
(21 rows)

--Testcase 307:
SELECT * FROM "type_FLOAT_INF+" ORDER BY f ASC, i;
Expand All @@ -1349,12 +1356,16 @@ SELECT * FROM "type_FLOAT_INF+" ORDER BY f ASC, i;
18 | Infinity | text | 9
20 | Infinity | text | 3
21 | Infinity | text | 4
(19 rows)
23 | NaN | text | 3
16 | | null |
(21 rows)

--Testcase 308:
SELECT * FROM "type_FLOAT_INF+" ORDER BY f DESC, i;
i | f | t | l
----+-----------+------+---
16 | | null |
23 | NaN | text | 3
2 | Infinity | real | 3
4 | Infinity | real | 3
10 | Infinity | real | 3
Expand All @@ -1374,13 +1385,14 @@ SELECT * FROM "type_FLOAT_INF+" ORDER BY f DESC, i;
15 | -Infinity | real | 4
19 | -Infinity | text | 9
22 | -Infinity | text | 4
(19 rows)
(21 rows)

--Testcase 309:
SELECT * FROM "type_FLOAT_INF+" WHERE f > '+Infinity' ORDER BY i;
i | f | t | l
---+---+---+---
(0 rows)
i | f | t | l
----+-----+------+---
23 | NaN | text | 3
(1 row)

--Testcase 310:
SELECT * FROM "type_FLOAT_INF+" WHERE f < '+Infinity' ORDER BY i;
Expand Down Expand Up @@ -1415,9 +1427,10 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = '+Infinity' ORDER BY i;

--Testcase 312:
SELECT * FROM "type_FLOAT_INF+" WHERE f > '+Inf' ORDER BY i;
i | f | t | l
---+---+---+---
(0 rows)
i | f | t | l
----+-----+------+---
23 | NaN | text | 3
(1 row)

--Testcase 313:
SELECT * FROM "type_FLOAT_INF+" WHERE f < '+Inf' ORDER BY i;
Expand Down Expand Up @@ -1467,7 +1480,8 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f > '-Infinity' ORDER BY i;
18 | Infinity | text | 9
20 | Infinity | text | 3
21 | Infinity | text | 4
(13 rows)
23 | NaN | text | 3
(14 rows)

--Testcase 316:
SELECT * FROM "type_FLOAT_INF+" WHERE f < '-Infinity' ORDER BY i;
Expand Down Expand Up @@ -1504,7 +1518,8 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f > '-Inf' ORDER BY i;
18 | Infinity | text | 9
20 | Infinity | text | 3
21 | Infinity | text | 4
(13 rows)
23 | NaN | text | 3
(14 rows)

--Testcase 319:
SELECT * FROM "type_FLOAT_INF+" WHERE f < '-Inf' ORDER BY i;
Expand All @@ -1526,9 +1541,10 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = '-Inf' ORDER BY i;

--Testcase 321:
SELECT * FROM "type_FLOAT_INF+" WHERE f > 'Infinity' ORDER BY i;
i | f | t | l
---+---+---+---
(0 rows)
i | f | t | l
----+-----+------+---
23 | NaN | text | 3
(1 row)

--Testcase 322:
SELECT * FROM "type_FLOAT_INF+" WHERE f < 'Infinity' ORDER BY i;
Expand Down Expand Up @@ -1563,9 +1579,10 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'Infinity' ORDER BY i;

--Testcase 324:
SELECT * FROM "type_FLOAT_INF+" WHERE f > 'Inf' ORDER BY i;
i | f | t | l
---+---+---+---
(0 rows)
i | f | t | l
----+-----+------+---
23 | NaN | text | 3
(1 row)

--Testcase 325:
SELECT * FROM "type_FLOAT_INF+" WHERE f < 'Inf' ORDER BY i;
Expand Down Expand Up @@ -1598,6 +1615,44 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'Inf' ORDER BY i;
21 | Infinity | text | 4
(10 rows)

--Testcase 327:
SELECT * FROM "type_FLOAT_INF+" WHERE f > 'NaN' ORDER BY i;
i | f | t | l
---+---+---+---
(0 rows)

--Testcase 328:
SELECT * FROM "type_FLOAT_INF+" WHERE f < 'NaN' ORDER BY i;
i | f | t | l
----+-----------+------+---
1 | -Infinity | real | 4
2 | Infinity | real | 3
3 | -Infinity | real | 4
4 | Infinity | real | 3
5 | -1e+308 | real | 9
6 | 0 | real | 3
7 | 1e+308 | real | 8
10 | Infinity | real | 3
11 | Infinity | real | 3
12 | -Infinity | real | 4
13 | Infinity | real | 3
14 | Infinity | real | 3
15 | -Infinity | real | 4
17 | Infinity | text | 8
18 | Infinity | text | 9
19 | -Infinity | text | 9
20 | Infinity | text | 3
21 | Infinity | text | 4
22 | -Infinity | text | 4
(19 rows)

--Testcase 329:
SELECT * FROM "type_FLOAT_INF+" WHERE f = 'NaN' ORDER BY i;
i | f | t | l
----+-----+------+---
23 | NaN | text | 3
(1 row)

--Testcase 330:
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM "type_FLOAT_INF+" WHERE f > '+Infinity' ORDER BY i;
Expand Down Expand Up @@ -1796,6 +1851,39 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'Inf' ORDER BY i;
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+" WHERE ((sqlite_fdw_float(`f`) = 9e999))
(6 rows)

--Testcase 348:
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM "type_FLOAT_INF+" WHERE f > 'NaN' ORDER BY i;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public."type_FLOAT_INF+"
Output: i, f, t, l
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+" WHERE ((sqlite_fdw_float(`f`) > 'NaN')) ORDER BY `i` ASC NULLS LAST
(3 rows)

--Testcase 349:
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM "type_FLOAT_INF+" WHERE f < 'NaN' ORDER BY i;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public."type_FLOAT_INF+"
Output: i, f, t, l
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+" WHERE ((sqlite_fdw_float(`f`) < 'NaN')) ORDER BY `i` ASC NULLS LAST
(3 rows)

--Testcase 350:
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM "type_FLOAT_INF+" WHERE f = 'NaN' ORDER BY i;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Sort
Output: i, f, t, l
Sort Key: "type_FLOAT_INF+".i
-> Foreign Scan on public."type_FLOAT_INF+"
Output: i, f, t, l
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+" WHERE ((sqlite_fdw_float(`f`) = 'NaN'))
(6 rows)

--Testcase 351:
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
--Testcase 352:
Expand Down
Loading

0 comments on commit befdc6d

Please sign in to comment.