Skip to content

Commit 3536796

Browse files
authored
RELEASE v2.4.0 (#86)
Co-authored-by: Nguyen Ngoc Son <jopoly>
1 parent 90dad0a commit 3536796

File tree

211 files changed

+88350
-18933
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

211 files changed

+88350
-18933
lines changed

META.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"name": "sqlite_fdw",
33
"abstract": "Foreign Data Wrapper for SQLite databases",
44
"description": "PostgreSQL extension which implements a Foreign Data Wrapper (FDW) for SQLite databases.",
5-
"version": "2.3.0",
5+
"version": "2.4.0",
66
"maintainer": "pgspider",
77
"license": "postgresql",
88
"provides": {
99
"sqlite_fdw": {
1010
"abstract": "Foreign Data Wrapper for SQLite databases",
1111
"file": "sqlite_fdw.c",
1212
"docfile": "README.md",
13-
"version": "2.3.0"
13+
"version": "2.4.0"
1414
}
1515
},
1616
"prereqs": {

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ include $(PGXS)
3737
ifndef MAJORVERSION
3838
MAJORVERSION := $(basename $(VERSION))
3939
endif
40-
ifeq (,$(findstring $(MAJORVERSION), 11 12 13 14 15))
41-
$(error PostgreSQL 11, 12, 13, 14 or 15 is required to compile this extension)
40+
ifeq (,$(findstring $(MAJORVERSION), 12 13 14 15 16))
41+
$(error PostgreSQL 12, 13, 14, 15 or 16 is required to compile this extension)
4242
endif
4343

4444
else

README.md

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ SQLite Foreign Data Wrapper for PostgreSQL
22
==========================================
33

44
This is a foreign data wrapper (FDW) to connect [PostgreSQL](https://www.postgresql.org/)
5-
to [SQLite](https://sqlite.org/) database file. This FDW works with PostgreSQL 11, 12, 13, 14, 15 and confirmed with SQLite 3.38.5.
5+
to [SQLite](https://sqlite.org/) database file. This FDW works with PostgreSQL 12, 13, 14, 15, 16 and confirmed with SQLite 3.42.0.
66

77
<img src="https://upload.wikimedia.org/wikipedia/commons/2/29/Postgresql_elephant.svg" align="center" height="100" alt="PostgreSQL"/> + <img src="https://upload.wikimedia.org/wikipedia/commons/3/38/SQLite370.svg" align="center" height="100" alt="SQLite"/>
88

@@ -93,7 +93,7 @@ For Debian or Ubuntu:
9393
`apt-get install libsqlite3-dev`
9494
`apt-get install postgresql-server-dev-XX`, where XX matches your postgres version, i.e. `apt-get install postgresql-server-dev-15`
9595

96-
You can also [download SQLite source code][1] and [build SQLite][2].
96+
You can also [download SQLite source code][1] and [build SQLite][2] with FTS5 for full-text search.
9797

9898
#### 2. Build and install sqlite_fdw
9999

@@ -120,31 +120,31 @@ Usage
120120
- **database** as *string*, **required**
121121

122122
SQLite database path.
123-
123+
124124
- **updatable** as *boolean*, optional, default *true*
125125

126126
This option allow or disallow write operations on SQLite database file.
127-
127+
128128
- **truncatable** as *boolean*, optional, default *true*
129129

130130
Allows foreign tables to be truncated using the `TRUNCATE` command.
131-
131+
132132
- **keep_connections** as *boolean*, optional, default *true*
133-
133+
134134
Allows to keep connections to SQLite while there is no SQL operations between PostgreSQL and SQLite.
135-
135+
136136
- **batch_size** as *integer*, optional, default *1*
137137

138138
Specifies the number of rows which should be inserted in a single `INSERT` operation. This setting can be overridden for individual tables.
139-
139+
140140
## CREATE USER MAPPING options
141141

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

144144
In OS `sqlite_fdw` works as executed code with permissions of user of PostgreSQL server. Usually it is `postgres` OS user. For interacting with SQLite database without access errors ensure this user have follow permissions:
145145
- read permission on all directories by path to the SQLite database file;
146146
- read permission on SQLite database file;
147-
- write permissions both on SQLite database file and *directory it contains* if you need a modification. During `INSERT`, `UPDATE` or `DELETE` in SQLite database, SQLite engine functions makes temporary files with transaction data in the directory near SQLite database file. Hence without write permissions you'll have a message `failed to execute remote SQL: rc=8 attempt to write a readonly database`.
147+
- write permissions both on SQLite database file and *directory it contains* if you need a modification. During `INSERT`, `UPDATE` or `DELETE` in SQLite database, SQLite engine functions makes temporary files with transaction data in the directory near SQLite database file. Hence without write permissions you'll have a message `failed to execute remote SQL: rc=8 attempt to write a readonly database`.
148148

149149
## CREATE FOREIGN TABLE options
150150

@@ -156,17 +156,17 @@ In OS `sqlite_fdw` works as executed code with permissions of user of PostgreSQL
156156
SQLite table name. Use if not equal to name of foreign table in PostgreSQL. Also see about [identifier case handling](#identifier-case-handling).
157157

158158
- **truncatable** as *boolean*, optional, default from the same `CREATE SERVER` option
159-
159+
160160
See `CREATE SERVER` options section for details.
161161

162162
- **batch_size** as *integer*, optional, default from the same `CREATE SERVER` option
163163

164-
See `CREATE SERVER` options section for details.
165-
164+
See `CREATE SERVER` options section for details.
165+
166166
- **updatable** as *boolean*, optional, default *true*
167167

168168
This option can allow or disallow write operations on a SQLite table independed of the same server option.
169-
169+
170170
`sqlite_fdw` accepts the following column-level options via the
171171
`CREATE FOREIGN TABLE` command:
172172

@@ -181,7 +181,7 @@ In OS `sqlite_fdw` works as executed code with permissions of user of PostgreSQL
181181
- **key** as *boolean*, optional, default *false*
182182

183183
Indicates a column as a part of primary key or unique key of SQLite table.
184-
184+
185185
## IMPORT FOREIGN SCHEMA options
186186

187187
`sqlite_fdw` supports [IMPORT FOREIGN SCHEMA](https://www.postgresql.org/docs/current/sql-importforeignschema.html)
@@ -218,9 +218,9 @@ functions, `sqlite_fdw` provides the following user-callable utility functions:
218218
- **sqlite_fdw_version()**;
219219
Returns standard "version integer" as `major version * 10000 + minor version * 100 + bugfix`.
220220
```
221-
sqlite_fdw_version
221+
sqlite_fdw_version
222222
--------------------
223-
20300
223+
20400
224224
```
225225
Identifier case handling
226226
------------------------
@@ -356,7 +356,7 @@ If you want to update tables, please add `OPTIONS (key 'true')` to a primary key
356356
a integer OPTIONS (key 'true'),
357357
b text
358358
)
359-
SERVER sqlite_server
359+
SERVER sqlite_server
360360
OPTIONS (
361361
table 't1_sqlite'
362362
);
@@ -438,35 +438,35 @@ Test directory have structure as following:
438438

439439
```sql
440440
+---sql
441-
| +---11.7
441+
| +---12.15
442442
| | filename1.sql
443443
| | filename2.sql
444-
| |
445-
| +---12.12
444+
| |
445+
| +---13.11
446446
| | filename1.sql
447447
| | filename2.sql
448-
| |
449-
.................
450-
| \---15.0
448+
| |
449+
.................
450+
| \---15.3
451451
| filename1.sql
452452
| filename2.sql
453-
|
453+
|
454454
\---expected
455-
| +---11.7
455+
| +---12.15
456456
| | filename1.out
457457
| | filename2.out
458-
| |
459-
| +---12.12
458+
| |
459+
| +---13.11
460460
| | filename1.out
461461
| | filename2.out
462-
| |
463-
.................
464-
| \---15.0
462+
| |
463+
.................
464+
| \---15.3
465465
filename1.out
466466
filename2.out
467467
```
468468
The test cases for each version are based on the test of corresponding version of PostgreSQL.
469-
You can execute test by test.sh directly.
469+
You can execute test by test.sh directly.
470470
The version of PostgreSQL is detected automatically by $(VERSION) variable in Makefile.
471471
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.
472472

connection.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,9 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
710710
MemoryContext oldcontext;
711711
#endif
712712

713-
#if PG_VERSION_NUM >= 150000
713+
#if PG_VERSION_NUM >= 160000
714+
InitMaterializedSRF(fcinfo, 0);
715+
#elif PG_VERSION_NUM >= 150000
714716
SetSingleFuncCall(fcinfo, 0);
715717
#else
716718
/* check to see if caller supports us returning a tuplestore */
@@ -754,17 +756,15 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
754756
while ((entry = (ConnCacheEntry *) hash_seq_search(&scan)))
755757
{
756758
ForeignServer *server;
757-
Datum values[SQLITE_FDW_GET_CONNECTIONS_COLS];
758-
bool nulls[SQLITE_FDW_GET_CONNECTIONS_COLS];
759+
Datum values[SQLITE_FDW_GET_CONNECTIONS_COLS] = {0};
760+
bool nulls[SQLITE_FDW_GET_CONNECTIONS_COLS] = {0};
759761

760762
/* We only look for open remote connections */
761763
if (!entry->conn)
762764
continue;
763765

764766
server = GetForeignServerExtended(entry->serverid, FSV_MISSING_OK);
765767

766-
MemSet(values, 0, sizeof(values));
767-
MemSet(nulls, 0, sizeof(nulls));
768768

769769
/*
770770
* The foreign server may have been dropped in current explicit
@@ -811,7 +811,7 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
811811
values[1] = BoolGetDatum(!entry->invalidated);
812812
#if PG_VERSION_NUM >= 150000
813813
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
814-
#else
814+
#else
815815
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
816816
#endif
817817
}

deparse.c

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include "catalog/pg_operator.h"
2525
#include "catalog/pg_opfamily.h"
2626
#include "catalog/pg_proc.h"
27+
#if PG_VERSION_NUM >= 160000
28+
#include "catalog/pg_ts_config.h"
29+
#endif
30+
#include "catalog/pg_ts_dict.h"
2731
#include "catalog/pg_type.h"
2832
#include "commands/defrem.h"
2933
#include "nodes/nodeFuncs.h"
@@ -108,7 +112,7 @@ static bool sqlite_foreign_expr_walker(Node *node,
108112
/*
109113
* Functions to construct string representation of a node tree.
110114
*/
111-
static void sqlite_deparse_expr(Expr *expr, deparse_expr_cxt *context);
115+
static void sqlite_deparse_expr(Expr *node, deparse_expr_cxt *context);
112116
static void sqlite_deparse_var(Var *node, deparse_expr_cxt *context);
113117
static void sqlite_deparse_const(Const *node, deparse_expr_cxt *context, int showtype);
114118
static void sqlite_deparse_param(Param *node, deparse_expr_cxt *context);
@@ -356,6 +360,7 @@ sqlite_is_foreign_pathkey(PlannerInfo *root,
356360
PathKey *pathkey)
357361
{
358362
EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
363+
EquivalenceMember *em;
359364

360365
/*
361366
* is_foreign_expr would detect volatile expressions as well, but checking
@@ -368,8 +373,34 @@ sqlite_is_foreign_pathkey(PlannerInfo *root,
368373
if (!sqlite_is_builtin(pathkey->pk_opfamily))
369374
return false;
370375

371-
/* can push if a suitable EC member exists */
372-
return (sqlite_find_em_for_rel(root, pathkey_ec, baserel) != NULL);
376+
/* Find a suitable EC member */
377+
em = sqlite_find_em_for_rel(root, pathkey_ec, baserel);
378+
if (em)
379+
{
380+
Oid oprid;
381+
TypeCacheEntry *typentry;
382+
383+
oprid = get_opfamily_member(pathkey->pk_opfamily,
384+
em->em_datatype,
385+
em->em_datatype,
386+
pathkey->pk_strategy);
387+
if (!OidIsValid(oprid))
388+
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
389+
pathkey->pk_strategy, em->em_datatype, em->em_datatype,
390+
pathkey->pk_opfamily);
391+
392+
/* See whether operator is default < or > for sort expr's datatype. */
393+
typentry = lookup_type_cache(exprType((Node *) em->em_expr),
394+
TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
395+
396+
/* SQLite does not support USING, so do not push down it */
397+
if (oprid != typentry->lt_opr && oprid != typentry->gt_opr)
398+
return false;
399+
}
400+
else
401+
return false;
402+
403+
return true;
373404
}
374405

375406
/*
@@ -3362,6 +3393,13 @@ sqlite_append_group_by_clause(List *tlist, deparse_expr_cxt *context)
33623393
*/
33633394
Assert(!query->groupingSets);
33643395

3396+
/*
3397+
* We intentionally print query->groupClause not processed_groupClause,
3398+
* leaving it to the remote planner to get rid of any redundant GROUP BY
3399+
* items again. This is necessary in case processed_groupClause reduced
3400+
* to empty, and in any case the redundancy situation on the remote might
3401+
* be different than what we think here.
3402+
*/
33653403
foreach(lc, query->groupClause)
33663404
{
33673405
SortGroupClause *grp = (SortGroupClause *) lfirst(lc);
@@ -3514,25 +3552,13 @@ static void sqlite_append_order_by_suffix(Oid sortop, Oid sortcoltype,
35143552
typentry = lookup_type_cache(sortcoltype,
35153553
TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
35163554

3555+
/* SQLite does not support USING */
3556+
Assert (sortop == typentry->lt_opr || sortop == typentry->gt_opr);
3557+
35173558
if (sortop == typentry->lt_opr)
35183559
appendStringInfoString(buf, " ASC");
35193560
else if (sortop == typentry->gt_opr)
35203561
appendStringInfoString(buf, " DESC");
3521-
else
3522-
{
3523-
HeapTuple opertup;
3524-
Form_pg_operator operform;
3525-
3526-
appendStringInfoString(buf, " USING ");
3527-
3528-
/* Append operator name. */
3529-
opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(sortop));
3530-
if (!HeapTupleIsValid(opertup))
3531-
elog(ERROR, "cache lookup failed for operator %u", sortop);
3532-
operform = (Form_pg_operator) GETSTRUCT(opertup);
3533-
sqlite_deparse_operator_name(buf, operform);
3534-
ReleaseSysCache(opertup);
3535-
}
35363562

35373563
if (nulls_first)
35383564
appendStringInfoString(buf, " NULLS FIRST");
@@ -3736,7 +3762,21 @@ sqlite_get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel,
37363762
i = 1;
37373763
foreach(lc, foreignrel->reltarget->exprs)
37383764
{
3765+
#if PG_VERSION_NUM >= 160000
3766+
Var *tlvar = (Var *) lfirst(lc);
3767+
3768+
/*
3769+
* Match reltarget entries only on varno/varattno. Ideally there
3770+
* would be some cross-check on varnullingrels, but it's unclear what
3771+
* to do exactly; we don't have enough context to know what that value
3772+
* should be.
3773+
*/
3774+
if (IsA(tlvar, Var) &&
3775+
tlvar->varno == node->varno &&
3776+
tlvar->varattno == node->varattno)
3777+
#else
37393778
if (equal(lfirst(lc), (Node *) node))
3779+
#endif
37403780
{
37413781
*colno = i;
37423782
return;

0 commit comments

Comments
 (0)