Skip to content

Commit ad0404c

Browse files
committed
Implement pure floating numbers mode
1 parent 0c46de4 commit ad0404c

27 files changed

+1040
-137
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ ifndef REGRESS
3636
REGRESS = libsqlite extra/sqlite_fdw_post $(DATA_TYPE_TESTS) extra/join extra/limit extra/aggregates extra/prepare extra/select_having extra/select extra/insert extra/update extra/encodings sqlite_fdw aggregate selectfunc $(GIS_DEP_TESTS)
3737
endif
3838

39-
# Other encodings also are tested. Client encoding should be UTF-8-
39+
# Other encodings also are tested. Client encoding should be UTF-8.
4040
REGRESS_OPTS = --encoding=utf8
4141

4242
UNAME = uname

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ Array support is experimental. Please be careful.
616616
- 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.
617617
- 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`.
618618
- 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`).
619+
- Please note you can turn off processing of IEEE 754-2008 values with `text` affiniy thorough `real` value of `column_type` option. This can increase `SELECT` or `ORDER` speed, becasuse there will be no normalize function wrapping, but in this case any query will have unsuccessfilly result in case of any value with `text` affiniy.
619620

620621
### Boolean values
621622
- `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`.

deparse.c

+41-11
Original file line numberDiff line numberDiff line change
@@ -2285,6 +2285,8 @@ sqlite_deparse_column_ref(StringInfo buf, int varno, int varattno, PlannerInfo *
22852285
ListCell *lc;
22862286
Oid pg_atttyp = InvalidOid;
22872287
bool no_unification = false;
2288+
char *coltype = NULL;
2289+
int colaff = SQLITE_NULL;
22882290

22892291
/* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
22902292
Assert(!IS_SPECIAL_VARNO(varno));
@@ -2301,9 +2303,15 @@ sqlite_deparse_column_ref(StringInfo buf, int varno, int varattno, PlannerInfo *
23012303
if (strcmp(def->defname, "column_name") == 0)
23022304
{
23032305
colname = defGetString(def);
2304-
elog(DEBUG3, "sqlite_fdw : %s, column_name opt = %s\n", __func__, colname);
2306+
elog(DEBUG1, "column name = %s\n", colname);
23052307
break;
23062308
}
2309+
if (strcmp(def->defname, "column_type") == 0)
2310+
{
2311+
coltype = defGetString(def);
2312+
elog(DEBUG4, "column type = %s", coltype);
2313+
colaff = sqlite_affinity_code(coltype);
2314+
}
23072315
}
23082316

23092317
/*
@@ -2332,12 +2340,22 @@ sqlite_deparse_column_ref(StringInfo buf, int varno, int varattno, PlannerInfo *
23322340
case FLOAT4OID:
23332341
case NUMERICOID:
23342342
{
2335-
elog(DEBUG2, "floatN unification for \"%s\"", colname);
2336-
appendStringInfoString(buf, "sqlite_fdw_float(");
2337-
if (qualify_col)
2338-
ADD_REL_QUALIFIER(buf, varno);
2339-
appendStringInfoString(buf, sqlite_quote_identifier(colname, '`'));
2340-
appendStringInfoString(buf, ")");
2343+
if (colaff != SQLITE_FLOAT)
2344+
{
2345+
elog(DEBUG2, "floatN unification for \"%s\"", colname);
2346+
appendStringInfoString(buf, "sqlite_fdw_float(");
2347+
if (qualify_col)
2348+
ADD_REL_QUALIFIER(buf, varno);
2349+
appendStringInfoString(buf, sqlite_quote_identifier(colname, '`'));
2350+
appendStringInfoString(buf, ")");
2351+
}
2352+
else
2353+
{
2354+
elog(DEBUG2, "floatN real affinity only for \"%s\"", colname);
2355+
if (qualify_col)
2356+
ADD_REL_QUALIFIER(buf, varno);
2357+
appendStringInfoString(buf, sqlite_quote_identifier(colname, '`'));
2358+
}
23412359
break;
23422360
}
23432361
case BOOLOID:
@@ -2966,6 +2984,21 @@ get_complementary_var_node(Expr *node)
29662984
}
29672985
}
29682986

2987+
/* IEEE 754-2008 : ∞ and NaN */
2988+
const char * CHAR_INF_SHORT = "Inf";
2989+
const char * CHAR_INF_LONG = "Infinity";
2990+
const char * CHAR_NAN = "NaN";
2991+
2992+
bool
2993+
isInfinity (const char * s)
2994+
{
2995+
return strcasecmp(s, CHAR_INF_SHORT) == 0 ||
2996+
strcasecmp(s, CHAR_INF_LONG) == 0 ||
2997+
strcasecmp(s + sizeof(char), CHAR_INF_SHORT) == 0 ||
2998+
strcasecmp(s + sizeof(char), CHAR_INF_LONG) == 0;
2999+
}
3000+
3001+
29693002
/*
29703003
* Deparse given constant value into context->buf.
29713004
*
@@ -3031,10 +3064,7 @@ sqlite_deparse_const(Const *node, deparse_expr_cxt *context, int showtype)
30313064
else
30323065
appendStringInfoString(buf, extval);
30333066
}
3034-
else if (strcasecmp(extval, infs) == 0 ||
3035-
strcasecmp(extval, infl) == 0 ||
3036-
strcasecmp(extval + 1, infs) == 0 ||
3037-
strcasecmp(extval + 1, infl) == 0)
3067+
else if (isInfinity(extval))
30383068
{
30393069
bool is_negative_or_positive = false;
30403070
if (extval[0] == '-' || extval[0] == '+')

expected/13.15/types/float4.out

+73-4
Original file line numberDiff line numberDiff line change
@@ -1885,12 +1885,81 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'NaN' ORDER BY i;
18851885
(6 rows)
18861886

18871887
--Testcase 351:
1888-
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
1888+
ALTER FOREIGN TABLE "type_FLOAT_INF" ALTER COLUMN f OPTIONS (ADD column_type 'real');
18891889
--Testcase 352:
1890-
DROP FOREIGN TABLE "type_FLOAT_INF";
1890+
EXPLAIN (VERBOSE, COSTS OFF)
1891+
SELECT * FROM "type_FLOAT_INF";
1892+
QUERY PLAN
1893+
------------------------------------------------------------
1894+
Foreign Scan on public."type_FLOAT_INF"
1895+
Output: i, f
1896+
SQLite query: SELECT `i`, `f` FROM main."type_FLOAT_INF"
1897+
(3 rows)
1898+
18911899
--Testcase 353:
1900+
EXPLAIN (VERBOSE, COSTS OFF)
1901+
SELECT * FROM "type_FLOAT_INF+";
1902+
QUERY PLAN
1903+
-----------------------------------------------------------------------------------------
1904+
Foreign Scan on public."type_FLOAT_INF+"
1905+
Output: i, f, t, l
1906+
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+"
1907+
(3 rows)
1908+
1909+
--Testcase 354: ERR - remove real
1910+
SELECT * FROM "type_FLOAT_INF";
1911+
ERROR: you should disable column_type = real for this column for infinity value processing
1912+
HINT: SQLite value with "text" affinity (8 bytes) : 'Infinity'
1913+
CONTEXT: foreign table "type_FLOAT_INF" foreign column "f" have data type "double precision" (usual affinity "real"), in query there is reference to foreign column
1914+
--Testcase 355:
1915+
DELETE FROM "type_FLOAT_INF" WHERE i IN (SELECT i FROM "type_FLOAT_INF+" WHERE t = 'text');
1916+
--Testcase 356:
1917+
SELECT * FROM "type_FLOAT_INF";
1918+
i | f
1919+
----+-----------
1920+
1 | -Infinity
1921+
2 | Infinity
1922+
3 | -Infinity
1923+
4 | Infinity
1924+
5 | -1e+308
1925+
6 | 0
1926+
7 | 1e+308
1927+
10 | Infinity
1928+
11 | Infinity
1929+
12 | -Infinity
1930+
13 | Infinity
1931+
14 | Infinity
1932+
15 | -Infinity
1933+
16 |
1934+
(14 rows)
1935+
1936+
--Testcase 357:
1937+
SELECT * FROM "type_FLOAT_INF+";
1938+
i | f | t | l
1939+
----+-----------+------+---
1940+
1 | -Infinity | real | 4
1941+
2 | Infinity | real | 3
1942+
3 | -Infinity | real | 4
1943+
4 | Infinity | real | 3
1944+
5 | -1e+308 | real | 9
1945+
6 | 0 | real | 3
1946+
7 | 1e+308 | real | 8
1947+
10 | Infinity | real | 3
1948+
11 | Infinity | real | 3
1949+
12 | -Infinity | real | 4
1950+
13 | Infinity | real | 3
1951+
14 | Infinity | real | 3
1952+
15 | -Infinity | real | 4
1953+
16 | | null |
1954+
(14 rows)
1955+
1956+
--Testcase 358:
1957+
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
1958+
--Testcase 359:
1959+
DROP FOREIGN TABLE "type_FLOAT_INF";
1960+
--Testcase 360:
18921961
DROP FOREIGN TABLE "type_FLOAT_INF+";
1893-
--Testcase 270:
1962+
--Testcase 390:
18941963
DROP SERVER sqlite_svr;
1895-
--Testcase 271:
1964+
--Testcase 391:
18961965
DROP EXTENSION sqlite_fdw CASCADE;

expected/13.15/types/float8.out

+73-4
Original file line numberDiff line numberDiff line change
@@ -2304,12 +2304,81 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'NaN' ORDER BY i;
23042304
(6 rows)
23052305

23062306
--Testcase 351:
2307-
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
2307+
ALTER FOREIGN TABLE "type_FLOAT_INF" ALTER COLUMN f OPTIONS (ADD column_type 'real');
23082308
--Testcase 352:
2309-
DROP FOREIGN TABLE "type_FLOAT_INF";
2309+
EXPLAIN (VERBOSE, COSTS OFF)
2310+
SELECT * FROM "type_FLOAT_INF";
2311+
QUERY PLAN
2312+
------------------------------------------------------------
2313+
Foreign Scan on public."type_FLOAT_INF"
2314+
Output: i, f
2315+
SQLite query: SELECT `i`, `f` FROM main."type_FLOAT_INF"
2316+
(3 rows)
2317+
23102318
--Testcase 353:
2319+
EXPLAIN (VERBOSE, COSTS OFF)
2320+
SELECT * FROM "type_FLOAT_INF+";
2321+
QUERY PLAN
2322+
-----------------------------------------------------------------------------------------
2323+
Foreign Scan on public."type_FLOAT_INF+"
2324+
Output: i, f, t, l
2325+
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+"
2326+
(3 rows)
2327+
2328+
--Testcase 354: ERR - remove real
2329+
SELECT * FROM "type_FLOAT_INF";
2330+
ERROR: you should disable column_type = real for this column for infinity value processing
2331+
HINT: SQLite value with "text" affinity (8 bytes) : 'Infinity'
2332+
CONTEXT: foreign table "type_FLOAT_INF" foreign column "f" have data type "double precision" (usual affinity "real"), in query there is reference to foreign column
2333+
--Testcase 355:
2334+
DELETE FROM "type_FLOAT_INF" WHERE i IN (SELECT i FROM "type_FLOAT_INF+" WHERE t = 'text');
2335+
--Testcase 356:
2336+
SELECT * FROM "type_FLOAT_INF";
2337+
i | f
2338+
----+-----------
2339+
1 | -Infinity
2340+
2 | Infinity
2341+
3 | -Infinity
2342+
4 | Infinity
2343+
5 | -1e+308
2344+
6 | 0
2345+
7 | 1e+308
2346+
10 | Infinity
2347+
11 | Infinity
2348+
12 | -Infinity
2349+
13 | Infinity
2350+
14 | Infinity
2351+
15 | -Infinity
2352+
16 |
2353+
(14 rows)
2354+
2355+
--Testcase 357:
2356+
SELECT * FROM "type_FLOAT_INF+";
2357+
i | f | t | l
2358+
----+-----------+------+---
2359+
1 | -Infinity | real | 4
2360+
2 | Infinity | real | 3
2361+
3 | -Infinity | real | 4
2362+
4 | Infinity | real | 3
2363+
5 | -1e+308 | real | 9
2364+
6 | 0 | real | 3
2365+
7 | 1e+308 | real | 8
2366+
10 | Infinity | real | 3
2367+
11 | Infinity | real | 3
2368+
12 | -Infinity | real | 4
2369+
13 | Infinity | real | 3
2370+
14 | Infinity | real | 3
2371+
15 | -Infinity | real | 4
2372+
16 | | null |
2373+
(14 rows)
2374+
2375+
--Testcase 358:
2376+
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
2377+
--Testcase 359:
2378+
DROP FOREIGN TABLE "type_FLOAT_INF";
2379+
--Testcase 360:
23112380
DROP FOREIGN TABLE "type_FLOAT_INF+";
2312-
--Testcase 270:
2381+
--Testcase 390:
23132382
DROP SERVER sqlite_svr;
2314-
--Testcase 271:
2383+
--Testcase 391:
23152384
DROP EXTENSION sqlite_fdw CASCADE;

expected/14.12/types/float4.out

+73-4
Original file line numberDiff line numberDiff line change
@@ -1907,12 +1907,81 @@ SELECT * FROM "type_FLOAT_INF+" WHERE f = 'NaN' ORDER BY i;
19071907
(6 rows)
19081908

19091909
--Testcase 351:
1910-
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
1910+
ALTER FOREIGN TABLE "type_FLOAT_INF" ALTER COLUMN f OPTIONS (ADD column_type 'real');
19111911
--Testcase 352:
1912-
DROP FOREIGN TABLE "type_FLOAT_INF";
1912+
EXPLAIN (VERBOSE, COSTS OFF)
1913+
SELECT * FROM "type_FLOAT_INF";
1914+
QUERY PLAN
1915+
------------------------------------------------------------
1916+
Foreign Scan on public."type_FLOAT_INF"
1917+
Output: i, f
1918+
SQLite query: SELECT `i`, `f` FROM main."type_FLOAT_INF"
1919+
(3 rows)
1920+
19131921
--Testcase 353:
1922+
EXPLAIN (VERBOSE, COSTS OFF)
1923+
SELECT * FROM "type_FLOAT_INF+";
1924+
QUERY PLAN
1925+
-----------------------------------------------------------------------------------------
1926+
Foreign Scan on public."type_FLOAT_INF+"
1927+
Output: i, f, t, l
1928+
SQLite query: SELECT `i`, sqlite_fdw_float(`f`), `t`, `l` FROM main."type_FLOAT_INF+"
1929+
(3 rows)
1930+
1931+
--Testcase 354: ERR - remove real
1932+
SELECT * FROM "type_FLOAT_INF";
1933+
ERROR: you should disable column_type = real for this column for infinity value processing
1934+
HINT: SQLite value with "text" affinity (8 bytes) : 'Infinity'
1935+
CONTEXT: foreign table "type_FLOAT_INF" foreign column "f" have data type "double precision" (usual affinity "real"), in query there is reference to foreign column
1936+
--Testcase 355:
1937+
DELETE FROM "type_FLOAT_INF" WHERE i IN (SELECT i FROM "type_FLOAT_INF+" WHERE t = 'text');
1938+
--Testcase 356:
1939+
SELECT * FROM "type_FLOAT_INF";
1940+
i | f
1941+
----+-----------
1942+
1 | -Infinity
1943+
2 | Infinity
1944+
3 | -Infinity
1945+
4 | Infinity
1946+
5 | -1e+308
1947+
6 | 0
1948+
7 | 1e+308
1949+
10 | Infinity
1950+
11 | Infinity
1951+
12 | -Infinity
1952+
13 | Infinity
1953+
14 | Infinity
1954+
15 | -Infinity
1955+
16 |
1956+
(14 rows)
1957+
1958+
--Testcase 357:
1959+
SELECT * FROM "type_FLOAT_INF+";
1960+
i | f | t | l
1961+
----+-----------+------+---
1962+
1 | -Infinity | real | 4
1963+
2 | Infinity | real | 3
1964+
3 | -Infinity | real | 4
1965+
4 | Infinity | real | 3
1966+
5 | -1e+308 | real | 9
1967+
6 | 0 | real | 3
1968+
7 | 1e+308 | real | 8
1969+
10 | Infinity | real | 3
1970+
11 | Infinity | real | 3
1971+
12 | -Infinity | real | 4
1972+
13 | Infinity | real | 3
1973+
14 | Infinity | real | 3
1974+
15 | -Infinity | real | 4
1975+
16 | | null |
1976+
(14 rows)
1977+
1978+
--Testcase 358:
1979+
DELETE FROM "type_FLOAT_INF" WHERE i >= 10;
1980+
--Testcase 359:
1981+
DROP FOREIGN TABLE "type_FLOAT_INF";
1982+
--Testcase 360:
19141983
DROP FOREIGN TABLE "type_FLOAT_INF+";
1915-
--Testcase 270:
1984+
--Testcase 390:
19161985
DROP SERVER sqlite_svr;
1917-
--Testcase 271:
1986+
--Testcase 391:
19181987
DROP EXTENSION sqlite_fdw CASCADE;

0 commit comments

Comments
 (0)