You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JSON + JSONB support, -> and ->> pushing down for JSON data (#109)
* JSON+JSONB operators -> and ->> pushing down implementation
* Add types/json test case set showing -> and ->> behaviour for both JSON and JSONB for both SELECT and WHERE usage contexts
* Add/restore JSONB missing support in existed code infrastructure
* Full SQLite jsonb support.
Also this foreign data wrapper (FDW) can connect PostgreSQL with [PostGIS](https://www.postgis.net/)
10
10
to [SpatiaLite](https://www.gaia-gis.it/fossil/libspatialite/index) SQLite database file. This FDW works with PostGIS 2+ and confirmed with SpatiaLite 5.1. See [GIS support description](GIS.md).
@@ -48,7 +48,8 @@ Features
48
48
- `bool`: `text`(1..5) and `int`,
49
49
- `double precision`, `float` and `numeric`: `real` values and special values with `text` affinity (`+Infinity`, `-Infinity`, `NaN`),
50
50
- `macaddr`: `text`(12..17) or `blob`(6) or `integer`,
51
-
- `macaddr8`: `text`(16..23) or `blob`(8) or `integer`.
51
+
- `macaddr8`: `text`(16..23) or `blob`(8) or `integer`,
52
+
- `json`: `text`(default) or `blob` as SQLite `jsonb` object.
52
53
- Support mixed SQLite [data affinity](https://www.sqlite.org/datatype3.html) output (`INSERT`/`UPDATE`) for such data types as
53
54
- `timestamp`: `text`(default) or `int`,
54
55
- `uuid`: `text`(36) or `blob`(16)(default),
@@ -66,12 +67,13 @@ Features
66
67
-`LIMIT` and `OFFSET` are pushdowned when all tables in the query are foreign tables belongs to the same PostgreSQL `FOREIGN SERVER` object.
67
68
- Support `GROUP BY`, `HAVING` push-down.
68
69
-`mod()` is pushdowned. In PostgreSQL this function gives [argument-dependend data type](https://www.postgresql.org/docs/current/functions-math.html), but result from SQLite always [have `real` affinity](https://www.sqlite.org/lang_mathfunc.html#mod).
69
-
-`=` operator for GIS data objects are pushdowned.
70
+
-`=` operator for GIS data objects is pushed down.
71
+
- Operators `->` and `->>` for `json` and `jsonb` are pushed down in `WHERE` clause.
70
72
-`upper`, `lower` and other character case functions are **not** pushed down because they does not work with UNICODE character in SQLite.
71
73
-`WITH TIES` option is **not** pushed down.
72
74
- Bit string `#` (XOR) operator is **not** pushed down because there is no equal SQLite operator.
73
75
- Operations with `macaddr` or `macaddr8` data are **not** pushed down.
74
-
-Operators for GIS data objects are **not** pushdowned except for `=`.
76
+
- GIS data oparators are **not** pushdowned except for `=`.
75
77
76
78
### Notes about pushing down
77
79
@@ -86,6 +88,8 @@ Features
86
88
-`sqlite_fdw` can return implementation-dependent order for column if the column is not specified in `ORDER BY` clause.
87
89
- When the column type is `varchar array`, if the string is shorter than the declared length, values of type character will be space-padded; values of type `character varying` will simply store the shorter string.
88
90
-[String literals for `boolean`](https://www.postgresql.org/docs/current/datatype-boolean.html) (`t`, `f`, `y`, `n`, `yes`, `no`, `on`, `off` etc. case insensitive) can be readed and filtred but cannot writed, because SQLite documentation recommends only `int` affinity values (`0` or `1`) for boolean data and usually text boolean data belongs to legacy datasets.
91
+
- Directry for SQLite foreign table you can use SQLite specific extractor operand for `->` or `->>` like `$.a.d[1]` in `WHERE` clause, but PostgreSQL will calculate result of equal expression in `SELECT` clause as `NULL`.
92
+
- If you will use unsupported by `sqlite_fdw` older SQLite versions from your OS, please note SQLite JSON processnig behaviour was unstable between 3.45.0 and 3.48.0 especially for negative array indexes. Please note this for explaining any unexpected results after `->` or `->>` operators or failed tests on your OS.
89
93
90
94
Also see [Limitations](#limitations)
91
95
@@ -124,11 +128,11 @@ For Debian or Ubuntu:
124
128
125
129
`apt-get install libspatialite-dev` - for SpatiaLite ↔ PostGIS transformations
126
130
127
-
Instead of `libsqlite3-dev` you can also [download SQLite source code][1] and [build SQLite][2] with FTS5 for full-text search.
131
+
Instead of system `libsqlite3-dev`from OS repository you can also [download SQLite source code][1] and [build separate SQLite version][2] with FTS5 for full-text search. The directory of this not OS SQLite library can be pointed as prefix in a command like `./configure --enable-fts5 --prefix=$SQLITE_FOR_TESTING_DIR` before `make` and `make install`.
128
132
129
133
#### 2. Build and install sqlite_fdw
130
134
131
-
`sqlite_fdw` does not require to be compiled with PostGIS and `libspatialite-dev`. They are used only for full test which includes test for GIS support.
135
+
`sqlite_fdw` does not require to be compiled with PostGIS and `libspatialite-dev`. They are used only for full tests which includes test for GIS support.
132
136
133
137
Before building please add a directory of `pg_config` to PATH or ensure `pg_config` program is accessible from command line only by the name.
134
138
@@ -138,12 +142,21 @@ make USE_PGXS=1
138
142
make install USE_PGXS=1
139
143
```
140
144
145
+
Build and install without GIS support against separate compiled and installed SQLite version placed at given path.
146
+
Example for `/opt/testing/other/SQLite/3.49.0`.
147
+
```sh
148
+
make USE_PGXS=1 SQLITE_FOR_TESTING_DIR=/opt/testing/other/SQLite/3.49.0
149
+
make install USE_PGXS=1 SQLITE_FOR_TESTING_DIR=/opt/testing/other/SQLite/3.49.0
150
+
```
151
+
141
152
Build and install with GIS support
142
153
```sh
143
154
make USE_PGXS=1 ENABLE_GIS=1
144
155
make install USE_PGXS=1 ENABLE_GIS=1
145
156
```
146
157
158
+
Also you can build against separate SQLite version and with GIS support using obvious combination of variables.
159
+
147
160
If you want to build `sqlite_fdw` in a source tree of PostgreSQL, use
148
161
```sh
149
162
make
@@ -233,7 +246,7 @@ This table represents `sqlite_fdw` behaviour if in PostgreSQL foreign table colu
233
246
***∅** - no support (runtime error)
234
247
***✔** - 1↔1, PostgreSQL datatype is equal to SQLite affinity
235
248
***✔-** - PostgreSQL datatype is equal to SQLite affinity, but possible out of range error
236
-
***V** - transparent transformation if possible
249
+
***V** - transparent transformation
237
250
***V+** - transparent transformation if possible
238
251
***i** - ISO:SQL transformation for some special constants
239
252
***?** - not described/not tested
@@ -248,7 +261,7 @@ SQLite `NULL` affinity always can be transparent converted for a nullable column
248
261
| bool | V | ∅ | T | i | ∅ | INT |
249
262
| bit(n) | V<br>(n<=64) | ∅ | ∅ | ∅ | ∅ | INT |
250
263
| bytea | ∅ | ∅ | ✔ | V | ? | BLOB |
251
-
| char(n) | ? | ? | T | ✔| V | TEXT |
264
+
| char(n) | ? | ? | T | ✔-| V | TEXT |
252
265
| date | V | V | T | V+ |`NULL`| ? |
253
266
| float4 | V+ | ✔ | ∅ | i |`NULL`| REAL |
254
267
| float8 | V+ | ✔ | ∅ | i |`NULL`| REAL |
@@ -257,17 +270,18 @@ SQLite `NULL` affinity always can be transparent converted for a nullable column
@@ -304,6 +318,8 @@ SQLite `NULL` affinity always can be transparent converted for a nullable column
304
318
| macaddr8 | macaddr8 |
305
319
|[geometry](GIS.md)| geometry |
306
320
|[geography](GIS.md)| geography |
321
+
| json | json |
322
+
| jsonb | jsonb |
307
323
308
324
**Note:** In case of `sqlite_fdw` compiling without GIS support, GIS data
309
325
types will be converted to `bytea`.
@@ -634,6 +650,33 @@ for `INSERT` and `UPDATE` commands. PostgreSQL supports both `blob` and `text` [
634
650
-`sqlite_fdw` PostgreSQL `macaddr`/`macaddr8` values support based on `int` SQLite data affinity, because there is no per bit operations for SQLite `blob` affinity data. For `macaddr` out of range error is possible because this type is 6 bytes length, but SQLite `int` can store value up to 8 bytes.
635
651
-`sqlite_fdw` doesn't pushdown any operations with MAC adresses because there is 3 possible affinities for it in SQLite: `integer`, `blob` and `text`.
636
652
653
+
### JSON support and operators
654
+
- Operators `->` and `->>` for `json` and `jsonb` are pushed down. This means if you deal with a foreign table only, you can use SQLite syntax of `->` and `->>` operators which is more rich than PostgreSQL syntax. In PostgreSQL this operators means only 1-leveled extraction after one call, but possible multilevel extraction in one call of the operator in SQLite. You can extract `'{"a": 2, "c": [4, 5, {"f": 7}]}' ->'c' -> 2` with result `{"f":7}` both for PostgreSQL and SQLite tables, but `'{"a": 2, "c": [4, 5, {"f": 7}]}' ->'$.c[2]'` possible only in SQLite and for a foreign table.
655
+
- For PostgreSQL numeric argument of `->` and `->>` operators means only coordinate inside of array. In SQLite transformable to number text argument of this operators also can extract array element. PostgreSQL differs `json -> (2::text)` and `json -> 2`, but SQLite not: `json -> '2'`.
656
+
- Please note you can turn off processing of normalizing possible SQLite `json` values with `text` affinity for a column with formal SQLite `json` data type as option `column_type` = `text`. This can increase `SELECT` or `ORDER` speed, because there will be no normalize function wrapping, but in this case any query will have unsuccessfully result in case of any value with `blob` affiniy including any possible SQLite `jsonb` value.
657
+
```sql
658
+
-- a query with normalization - standard ISO:SQL behaviour
@@ -671,6 +714,7 @@ The test cases for each version are based on the test of corresponding version o
671
714
You can execute test by test.sh directly.
672
715
The version of PostgreSQL is detected automatically by $(VERSION) variable in Makefile.
673
716
The corresponding sql and expected directory will be used to compare the result. For example, for Postgres 15.0, you can execute "test.sh" directly, and the sql/15.0 and expected/15.0 will be used to compare automatically.
717
+
Please don't forget a command like `export SQLITE_FOR_TESTING_DIR=` with the same path as in SQLite's `./configure --prefix` berfore testing if you want to test not against your OS SQLite version, but against separate downloaded, compiled and installed SQLite version.
674
718
675
719
Test data directory is `/tmp/sqlite_fdw_test`. If you have `/tmp` mounted as `tmpfs` the tests will be up to 800% faster.
0 commit comments