Skip to content

Commit

Permalink
Refactor README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
mkgrgis committed Apr 13, 2024
1 parent 7b4ec52 commit 087b3a3
Showing 1 changed file with 66 additions and 58 deletions.
124 changes: 66 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Features

### Common features
- Transactions
- Support `INSERT`/`UPDATE`/`DELETE` (both Direct modification and Foreign modification), see [data modification access](#data-modification-access) about conditions of succesfully data modification.
- Support `INSERT`/`UPDATE`/`DELETE` (both Direct modification and Foreign modification), see [access control](#connection-to-sqlite-database-file-and-access-control) about conditions of succesfully data modification.
- Support `TRUNCATE` by deparsing into `DELETE` statement without `WHERE` clause.
- Allow control over whether foreign servers keep connections open after transaction completion. This is controlled by `keep_connections` and defaults to on.
- Support list cached connections to foreign servers by using function `sqlite_fdw_get_connections()`
Expand All @@ -52,7 +52,7 @@ Features
- `CASE` expressions are pushdowned.
- `LIMIT` and `OFFSET` are pushdowned (*when all tables queried are fdw)
- Support `GROUP BY`, `HAVING` push-down.
- `mod()` is pushdowned. In PostgreSQL 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).
- `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).
- `upper`, `lower` and other character case functions are **not** pushed down because they does not work with UNICODE character in SQLite.
- `WITH TIES` option is **not** pushed down.
- Bit string `#` (XOR) operator is **not** pushed down because there is no equal SQLite operator.
Expand Down Expand Up @@ -123,43 +123,6 @@ make install
Usage
-----

### Datatypes
**WARNING! The table above represents roadmap**, work still in progress. Untill it will be ended please refer real behaviour in non-obvious cases, where there is no ✔ or ∅ mark.

This table represents `sqlite_fdw` behaviour if in PostgreSQL foreign table column some [affinity](https://www.sqlite.org/datatype3.html) of SQLite data is detected. Some details about data values support see in [limitations](#limitations).

* **** - no support (runtime error)
* **V** - transparent transformation
* **T** - cast to text in SQLite utf-8 encoding, then to **PostgreSQL text with current encoding of database** and then transparent transformation if applicable
* **** - transparent transformation where PostgreSQL datatype is equal to SQLite affinity
* **V+** - transparent transformation if appliacable
* **?** - not described/not tested
* **-** - transparent transformation is possible for PostgreSQL (always or for some special values), but not implemented in `sqlite_fdw`.

SQLite `NULL` affinity always can be transparent converted for a nullable column in PostgreSQL.

| PostgreSQL | SQLite <br> INT | SQLite <br> REAL | SQLite <br> BLOB | SQLite <br> TEXT | SQLite <br> TEXT but <br>empty|SQLite<br>nearest<br>affinity|
|-------------:|:------------:|:------------:|:------------:|:------------:|:------------:|-------------:|
| bool | V || T | V+ || INT |
| bit(n) | V n<=64 ||||| INT |
| bytea |||| - | ? | BLOB |
| date | V | V | T | V+ | `NULL` | ? |
| float4 | V+ || T | - | `NULL` | REAL |
| float8 | V+ || T | - | `NULL` | REAL |
| int2 | V+ | ? | T | - | `NULL` | INT |
| int4 | V+ | ? | T | - | `NULL` | INT |
| int8 || ? | T | - | `NULL` | INT |
| json | ? | ? | T | V+ | ? | TEXT |
| name | ? | ? | T | V | `NULL` | TEXT |
| numeric | V | V | T || `NULL` | REAL |
| text | ? | ? | T || V | TEXT |
| time | V | V | T | V+ | `NULL` | ? |
| timestamp | V | V | T | V+ | `NULL` | ? |
|timestamp + tz| V | V | T | V+ | `NULL` | ? |
| uuid |||V+<br>(only<br>16 bytes)| V+ || TEXT, BLOB |
| varchar | ? | ? | T || V | TEXT |
| varbit(n) | V n<=64 || V ||| INT |

### CREATE SERVER options

`sqlite_fdw` accepts the following options via the `CREATE SERVER` command:
Expand All @@ -170,11 +133,11 @@ SQLite `NULL` affinity always can be transparent converted for a nullable column

- **updatable** as *boolean*, optional, default *true*

This option can allow or disallow data modification on foreign server for all foreign objects by default. Please note, this option can be overwritten on table level or have no effect because of some filesystem restrictions, see [data modification access](#data-modification-access) about conditions of succesfully data modification. This is only recommentadion of PostgreSQL foreign server owner user not to modify data in foreign server tables. For strong restriction see the next option `force_readonly`.
This option can allow or disallow data modification on foreign server for all foreign objects by default. Please note, this option can be overwritten on table level or have no effect because of some filesystem restrictions, see [connection to SQLite database file and access control](#connection-to-sqlite-database-file-and-access-control). This is only recommentadion of PostgreSQL foreign server owner user not to modify data in foreign server tables. For strong restriction see the next option `force_readonly`.

- **force_readonly** as *boolean*, optional, default *false*

This option can disallow any write operations on foreign server user data througth SQLite file readonly access mode. This option driven only by foreign server owner role can not be overwritten by any `updatable` option value. This is a strong restiction by PostgreSQL foreign server owner user not to modify data in any foreign server tables. Also see [data modification access](#data-modification-access) about conditions of succesfully data modification.
This option can disallow any write operations on foreign server user data througth SQLite file readonly access mode. This option driven only by foreign server owner role can not be overwritten by any `updatable` option value. This is a strong restiction by PostgreSQL foreign server owner user not to modify data in any foreign server tables. Also see [Connection to SQLite database file and access control](#connection-to-sqlite-database-file-and-access-control).

- **truncatable** as *boolean*, optional, default *false*

Expand All @@ -192,7 +155,7 @@ SQLite `NULL` affinity always can be transparent converted for a nullable column

There is no user or password conceptions in SQLite, hence `sqlite_fdw` no need any `CREATE USER MAPPING` command.

About access model and possible data modifications problems see [data modification access](#data-modification-access).
About access model and possible data modifications problems see about [connection to SQLite database file and access control](#connection-to-sqlite-database-file-and-access-control).

### CREATE FOREIGN TABLE options

Expand All @@ -213,7 +176,7 @@ About access model and possible data modifications problems see [data modificati

- **updatable** as *boolean*, optional, default *true*

This option can allow or disallow data modification on foreing table. Please note, this option can have no effect if foreign server option `force_readonly` = `true` or depends on filesystem context, see [data modification access](#data-modification-access).
This option can allow or disallow data modification on separate foreign table. Please note, this option can have no effect if there is foreign server option `force_readonly` = `true` or depends on filesystem context, see about [connection to SQLite database file and access control](#connection-to-sqlite-database-file-and-access-control).

`sqlite_fdw` accepts the following column-level options via the
`CREATE FOREIGN TABLE` command:
Expand All @@ -234,6 +197,43 @@ in SQLite (mixed affinity case). Updated and inserted values will have this affi

Indicates a column as a part of primary key or unique key of SQLite table.

#### Datatypes
**WARNING! The table above represents roadmap**, work still in progress. Untill it will be ended please refer real behaviour in non-obvious cases, where there is no ✔ or ∅ mark.

This table represents `sqlite_fdw` behaviour if in PostgreSQL foreign table column some [affinity](https://www.sqlite.org/datatype3.html) of SQLite data is detected. Some details about data values support see in [limitations](#limitations).

* **** - no support (runtime error)
* **V** - transparent transformation
* **T** - cast to text in SQLite utf-8 encoding, then to **PostgreSQL text with current encoding of database** and then transparent transformation if applicable
* **** - transparent transformation where PostgreSQL datatype is equal to SQLite affinity
* **V+** - transparent transformation if appliacable
* **?** - not described/not tested
* **-** - transparent transformation is possible for PostgreSQL (always or for some special values), but not implemented in `sqlite_fdw`.

SQLite `NULL` affinity always can be transparent converted for a nullable column in PostgreSQL.

| PostgreSQL | SQLite <br> INT | SQLite <br> REAL | SQLite <br> BLOB | SQLite <br> TEXT | SQLite <br> TEXT but <br>empty|SQLite<br>nearest<br>affinity|
|-------------:|:------------:|:------------:|:------------:|:------------:|:------------:|-------------:|
| bool | V || T | V+ || INT |
| bit(n) | V n<=64 ||||| INT |
| bytea |||| - | ? | BLOB |
| date | V | V | T | V+ | `NULL` | ? |
| float4 | V+ || T | - | `NULL` | REAL |
| float8 | V+ || T | - | `NULL` | REAL |
| int2 | V+ | ? | T | - | `NULL` | INT |
| int4 | V+ | ? | T | - | `NULL` | INT |
| int8 || ? | T | - | `NULL` | INT |
| json | ? | ? | T | V+ | ? | TEXT |
| name | ? | ? | T | V | `NULL` | TEXT |
| numeric | V | V | T || `NULL` | REAL |
| text | ? | ? | T || V | TEXT |
| time | V | V | T | V+ | `NULL` | ? |
| timestamp | V | V | T | V+ | `NULL` | ? |
|timestamp + tz| V | V | T | V+ | `NULL` | ? |
| uuid |||V+<br>(only<br>16 bytes)| V+ || TEXT, BLOB |
| varchar | ? | ? | T || V | TEXT |
| varbit(n) | V n<=64 || V ||| INT |

### IMPORT FOREIGN SCHEMA options

`sqlite_fdw` supports [IMPORT FOREIGN SCHEMA](https://www.postgresql.org/docs/current/sql-importforeignschema.html)
Expand Down Expand Up @@ -262,6 +262,7 @@ in SQLite (mixed affinity case). Updated and inserted values will have this affi
| datetime | timestamp |
| time | time |
| date | date |
| uuid | uuid |

### TRUNCATE support

Expand All @@ -277,23 +278,30 @@ Following restrictions apply:
- `TRUNCATE ... RESTART IDENTITY` is not supported
- SQLite tables with foreign key references can cause errors during truncating

### Data modification access
### Connection to SQLite database file and access control

In OS `sqlite_fdw` works as executed code with permissions of user of PostgreSQL server. Usually it is `postgres` OS user.

Data modification access in `sqlite_fdw` drived by both operating system and PostgreSQL. OS restrictions can disallow any SQLite data modifications and any PostgreSQL options context about data modification will have absolutely no effect. SQLite data modification will be succesfully only if there is all necessary conditions on both operating system and PostgreSQL levels.
#### Data read access
For succesfully connection to SQLite database file you must have at least existed and correct SQLite file readable for OS user of PostgreSQL server process. This means all directories by path to the file must be also readable (listable) for OS user of PostgreSQL server process. There are no other conditions for PostreSQL database superuser to read all of SQLite data if there are also `sqlite_fdw` extension in the database and `FOREIGN SERVER` for SQLite database file.

#### OS permissions
In OS `sqlite_fdw` works as executed code with permissions of user of PostgreSQL server. Usually it is `postgres` OS user. For **any** access to SQLite database such filesystem permissions for PostgreSQL server OS user are absolutely necessary:
- read permission on all directories by path to the SQLite database file,
- read permission on SQLite database file.
#### Data change access

For SQLite data **modification** such _additional_ filesystem permissions for PostgreSQL server OS user are absolutely necessary:
- write permission on a directory of SQLite database file (because SQLite creates some temporary transaction files),
- write permission on SQLite database file.
Data modification access in `sqlite_fdw` drived by both operating system and PostgreSQL.
OS restrictions can disallow any SQLite data modifications. Hence any PostgreSQL `FOREIGN SERVER` or `FOREIGN TABLE` options or `GRANT`s can be absolutely not effective. In this case SQLite data modification operations allowed by PostgreSQL can cause error message from SQLite like `attempt to write a readonly database` with result code `8`.

Otherwise there will be shown error message from SQLite like `failed to execute remote SQL: rc=8 attempt to write a readonly database`.
Full list of OS-leveled conditions of data modification access to SQLite database file
- Existed SQLite file is not corrupted by SQLite engine conditions.
- All path elements of the file are readable (listable) for OS user of PostgreSQL server process.
- The file and a direcotory of the file placed on readwrite filesystem. For example `sqashfs` is always read-only, remote `sshfs` can be read-only, a disk partition can be mounted in read-only mode etc.
- The file is writable for OS user of PostgreSQL server process.
- The directory of the file is writable for OS user of PostgreSQL server process because SQLite creates some temporary transaction files.

#### PostgreSQL options/permissions
On PostgreSQL level for data modification you should first ensure foreign server have no `force_readonly` = `true` option value. Second you should ensure there is no `updatable` = `false` option value on table level or, if there is no `updatable` option on table level you should ensure there is no `updatable` = `false` option value on foreign server level.
Full list of PostgreSQL-leveled conditions of data modification access to SQLite database file
- The `FOREIGN SERVER` of the SQLite file have no `force_readonly` = `true` option value.
- You have `USAGE` `GRANT` for the `FOREIGN SERVER`.
- The `FOREIGN TABLE` of SQLite table have no `updatable` = `false` option value.
- If the `FOREIGN TABLE` have no `updatable` option, ensure `FOREIGN TABLE` have no `updatable` = `false` option value.

Functions
---------
Expand Down Expand Up @@ -321,7 +329,7 @@ Identifier case handling
------------------------

PostgreSQL folds identifiers to lower case by default, SQLite is case insensitive by default
and doesn't differ uppercase and lowercase ASCII base latin letters. It's important
only for uppercase and lowercase ASCII base latin letters. It's important
to be aware of potential issues with table and column names.

Following SQL isn't correct for SQLite: `Error: duplicate column name: a`, but is correct for PostgreSQL
Expand Down Expand Up @@ -360,7 +368,7 @@ For SQLite there is no difference between
```
For PostgreSQL the query with comment `№4` is independend query to table `T`, not to table `t` as other queries.
Please note this table name composed from ASCII base latin letters *only*. This is not applicable for other
alphabet systems or mixed names. This is because `toLower` operation in PostgreSQL is Unicode opration but
alphabet systems or mixed names. This is because `toLower` operation in PostgreSQL is Unicode operation but
ASCII only operation in SQLite, hence other characters will not be changed.

```sql
Expand Down Expand Up @@ -420,7 +428,7 @@ stored in SQLite, only [`PRAGMA encoding;`](https://www.sqlite.org/pragma.html#p
When `sqlite_fdw` connects to a SQLite, all strings are interpreted acording the PostgreSQL database's server encoding.
It's not a problem if your PostgreSQL database encoding belongs to Unicode family. Otherewise interpretation transformation problems can occur. Some unproper for PostgreSQL database encoding characters will be replaced to default 'no such character' character or there will error like `character with byte sequence 0x** in encoding "UTF8" has no equivalent in encoding "**"`.

Character case functions such as `upper`, `lower` and other are not pushed down because they does not work with UNICODE character in SQLite.
Character case functions such as `upper`, `lower` and other are not pushed down because they does not work with Unocdoe character in SQLite.

`Sqlite_fdw` tested with PostgreSQL database encodings `EUC_JP`, `EUC_KR`, `ISO_8859_5`, `ISO_8859_6`, `ISO_8859_7`, `ISO_8859_8`, `LATIN1`, `LATIN2`, `LATIN3`, `LATIN4`, `LATIN5`, `LATIN6`, `LATIN7`, `LATIN8`, `LATIN9`, `LATIN9`, `LATIN10`, `WIN1250`, `WIN1251`, `WIN1252`, `WIN1253`, `WIN1254`, `WIN1255`, `WIN1256`, `WIN1257` and it's synomyms. Some other encodings also can be supported, but not tested.

Expand Down

0 comments on commit 087b3a3

Please sign in to comment.