Skip to content

Commit 31133bd

Browse files
authored
Merge pull request #52 from jopoly/RELEASE_v2.2.0
RELEASE v2.2.0
2 parents 9cffd29 + fc708d7 commit 31133bd

File tree

208 files changed

+22707
-11680
lines changed

Some content is hidden

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

208 files changed

+22707
-11680
lines changed

License

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
SQLite Foreign Data Wrapper for PostgreSQL
22

3-
Copyright (c) 2017 - 2021, TOSHIBA Corporation
3+
Copyright (c) 2018, TOSHIBA CORPORATION
44
Copyright (c) 2011 - 2016, EnterpriseDB Corporation
55

66
Permission to use, copy, modify, and distribute this software and its
@@ -17,4 +17,4 @@ TOSHIBA CORPORATION SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
1717
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1818
PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
1919
TOSHIBA CORPORATION HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
20-
UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
20+
UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

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.1.1",
5+
"version": "2.2.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.1.1"
13+
"version": "2.2.0"
1414
}
1515
},
1616
"prereqs": {

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SQLite Foreign Data Wrapper for PostgreSQL
44
#
5-
# Portions Copyright (c) 2021, TOSHIBA CORPORATION
5+
# Portions Copyright (c) 2018, TOSHIBA CORPORATION
66
#
77
# IDENTIFICATION
88
# Makefile
@@ -36,8 +36,8 @@ include $(PGXS)
3636
ifndef MAJORVERSION
3737
MAJORVERSION := $(basename $(VERSION))
3838
endif
39-
ifeq (,$(findstring $(MAJORVERSION), 10 11 12 13 14))
40-
$(error PostgreSQL 10, 11, 12, 13 or 14 is required to compile this extension)
39+
ifeq (,$(findstring $(MAJORVERSION), 11 12 13 14 15))
40+
$(error PostgreSQL 11, 12, 13, 14 or 15 is required to compile this extension)
4141
endif
4242

4343
else
@@ -54,4 +54,4 @@ REGRESS_PREFIX_SUB = $(VERSION)
5454
endif
5555

5656
REGRESS := $(addprefix $(REGRESS_PREFIX_SUB)/,$(REGRESS))
57-
$(shell mkdir -p results/$(REGRESS_PREFIX_SUB)/extra)
57+
$(shell mkdir -p results/$(REGRESS_PREFIX_SUB)/extra)

README.md

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SQLite Foreign Data Wrapper for PostgreSQL
22
This PostgreSQL extension is a Foreign Data Wrapper for [SQLite][1].
33

4-
The current version can work with PostgreSQL 10, 11, 12, 13 and 14.
4+
The current version can work with PostgreSQL 11, 12, 13, 14 and 15.
55

66
## Installation
77
### 1. Install SQLite library
@@ -28,6 +28,18 @@ make install
2828
</pre>
2929

3030
## Usage
31+
32+
### FDW options
33+
34+
| **No** | Option name | Context | Required | Description |
35+
|--------|-------------|---------|----------|-------------|
36+
| 1 | database | SERVER | Required | SQLite database path. |
37+
| 2 | table | FOREIGN TABLE | Required | SQLite table name. |
38+
| 3 | key | ATTRIBUTE | Optional | Primary key or unique key of SQLite table. |
39+
| 4 | column_type | ATTRIBUTE | Optional | Option to convert INT SQLite column (epoch Unix Time) to be treated/visualized as TIMESTAMP in PostgreSQL. |
40+
| 5 | column_name | ATTRIBUTE | Optional | This option gives the column name to use for the column on the remote server. |
41+
| 6 | truncatable | SERVER,<br>FOREIGN TABLE | Optional | This option controls whether sqlite_fdw allows foreign tables to be truncated using the TRUNCATE command. |
42+
3143
### Load extension
3244
<pre>
3345
CREATE EXTENSION sqlite_fdw;
@@ -67,11 +79,12 @@ SELECT * FROM t1;
6779
</pre>
6880

6981
## Features
70-
- Support update to foreign table
82+
- Support INSERT/UPDATE/DELETE (both Direct modification and Foreign modification).
7183
- WHERE clauses are pushdowned
7284
- Aggregate function are pushdowned
7385
- Order By is pushdowned
74-
- Joins (left/right/inner) are pushdowned
86+
- Joins (left/right/inner/cross) are pushdowned
87+
- CASE expressions are pushdowned.
7588
- Limit and Offset are pushdowned (*when all tables queried are fdw)
7689
- Transactions
7790
- Support TRUNCATE by deparsing into DELETE statement without WHERE clause
@@ -80,17 +93,34 @@ SELECT * FROM t1;
8093
- Support discard cached connections to foreign servers by using function sqlite_fdw_disconnect(), sqlite_fdw_disconnect_all().
8194
- Support Bulk Insert by using batch_size option
8295
- Support Insert/Update with generated column
83-
96+
- Support GROUP BY, HAVING push-down.
97+
- Support ON CONFLICT DO NOTHING.
8498
## Limitations
8599
- `COPY` command for foreign tables is not supported
86100
- IMPORT of generated column is not supported
87-
- Insert into a partitioned table which has foreign partitions is not supported
101+
- Insert into a partitioned table which has foreign partitions is not supported. Error "Not support partition insert" will display.
88102
- TRUNCATE in sqlite_fdw always delete data of both parent and child tables (no matter user inputs `TRUNCATE table CASCADE` or `TRUNCATE table RESTRICT`) if there are foreign-keys references with "ON DELETE CASCADE" clause.
103+
- RETURNING is not supported.
104+
105+
## Notes
106+
- SQLite evaluates division by zero as NULL. It is different from PostgreSQL, which will display "Division by zero" error.
107+
- The data type of column of foreign table should match with data type of column in SQLite to avoid wrong result. For example, if the column of SQLite is float (which will be stored as float8), the column of foreign table should be float8, too. If the column of foreign table is float4, it may cause wrong result when select.
108+
- For 'key' option, user needs to specify the primary key column of SQLite table corresponding with the 'key' option. If not, wrong result may occur when update or delete.
109+
- When Sum of data in table is out of range, SQLite FDW will display "Infinity" value. It is different from PostgreSQL FDW, which will display "ERROR: value out of range: overflow" error.
110+
- For push-down case, the number after floating point may be different from the result of PostgreSQL.
111+
- For numeric type, SQLite FDW use sqlite3_column_double to get value, while SQLite shell uses sqlite3_column_text to get value. Those 2 APIs may return different numeric value. Therefore, for numeric type, the value returned from SQLite FDW may different from the value returned from SQLite shell.
112+
- SQLite FDW can return implementation-dependent order for column if the column is not specified in ORDER BY clause.
113+
- WITH TIES option is not pushed down.
114+
- upper, lower functions are not pushed down because they does not work with UNICODE character in SQLite.
115+
- 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.
116+
- SQLite FDW only supports ARRAY const, for example, ANY (ARRAY[1, 2, 3]) or ANY ('{1, 2 ,3}'). SQlite FDW does not support ARRAY expression, for example, ANY (ARRAY[c1, 1, c1+0]). For ANY(ARRAY) clause, SQLite FDW deparses it using IN operator.
117+
- For sum function of SQLite, output of sum(bigint) is integer value. If input values are big, the overflow error may occurs on SQLite because it overflow within the range of signed 64bit. For PostgreSQL, it can calculate as over the precision of bigint, so overflow does not occur.
118+
- 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.
89119
## Contributing
90120
Opening issues and pull requests on GitHub are welcome.
91121

92122
## License
93-
Copyright (c) 2017 - 2021, TOSHIBA Corporation
123+
Copyright (c) 2018, TOSHIBA CORPORATION
94124
Copyright (c) 2011 - 2016, EnterpriseDB Corporation
95125

96126
Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.

connection.c

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* SQLite Foreign Data Wrapper for PostgreSQL
44
*
5-
* Portions Copyright (c) 2021, TOSHIBA CORPORATION
5+
* Portions Copyright (c) 2018, TOSHIBA CORPORATION
66
*
77
* IDENTIFICATION
88
* connection.c
@@ -59,7 +59,7 @@ typedef struct ConnCacheEntry
5959
static HTAB *ConnectionHash = NULL;
6060

6161
/* tracks whether any work is needed in callback functions */
62-
static bool xact_got_connection = false;
62+
static volatile bool xact_got_connection = false;
6363

6464
PG_FUNCTION_INFO_V1(sqlite_fdw_get_connections);
6565
PG_FUNCTION_INFO_V1(sqlite_fdw_disconnect);
@@ -69,11 +69,13 @@ static void sqlite_make_new_connection(ConnCacheEntry *entry, ForeignServer *ser
6969
void sqlite_do_sql_command(sqlite3 * conn, const char *sql, int level);
7070
static void sqlite_begin_remote_xact(ConnCacheEntry *entry);
7171
static void sqlitefdw_xact_callback(XactEvent event, void *arg);
72+
static void sqlitefdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel);
7273
static void sqlitefdw_subxact_callback(SubXactEvent event,
7374
SubTransactionId mySubid,
7475
SubTransactionId parentSubid,
7576
void *arg);
7677
static void sqlitefdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue);
78+
static void sqlitefdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel);
7779
#if PG_VERSION_NUM >= 140000
7880
static bool sqlite_disconnect_cached_connections(Oid serverid);
7981
#endif
@@ -434,23 +436,30 @@ sqlitefdw_xact_callback(XactEvent event, void *arg)
434436
case XACT_EVENT_PARALLEL_ABORT:
435437
case XACT_EVENT_ABORT:
436438
{
437-
elog(DEBUG3, "abort transaction");
438-
439-
/* Finalize all prepared statements */
440-
sqlite_finalize_list_stmt(&entry->stmtList);
441-
442-
/*
443-
* rollback if in transaction because SQLite may
444-
* already rollback
445-
*/
446-
if (!sqlite3_get_autocommit(entry->conn))
447-
sqlite_do_sql_command(entry->conn, "ROLLBACK", WARNING);
448-
439+
sqlitefdw_abort_cleanup(entry, true);
449440
break;
450441
}
451442
}
452443
}
453444

445+
/* Reset state to show we're out of a transaction */
446+
sqlitefdw_reset_xact_state(entry, true);
447+
}
448+
449+
/*
450+
* Regardless of the event type, we can now mark ourselves as out of the
451+
* transaction. (Note: if we are here during PRE_COMMIT or PRE_PREPARE,
452+
* this saves a useless scan of the hashtable during COMMIT or PREPARE.)
453+
*/
454+
xact_got_connection = false;
455+
}
456+
457+
/*
458+
* sqlitefdw_reset_xact_state --- Reset state to show we're out of a (sub)transaction
459+
*/
460+
static void
461+
sqlitefdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel) {
462+
if (toplevel) {
454463
/* Reset state to show we're out of a transaction */
455464
entry->xact_depth = 0;
456465

@@ -467,16 +476,11 @@ sqlitefdw_xact_callback(XactEvent event, void *arg)
467476
sqlite3_close(entry->conn);
468477
entry->conn = NULL;
469478
}
479+
} else {
480+
/* Reset state to show we're out of a subtransaction */
481+
entry->xact_depth--;
470482
}
471-
472-
/*
473-
* Regardless of the event type, we can now mark ourselves as out of the
474-
* transaction. (Note: if we are here during PRE_COMMIT or PRE_PREPARE,
475-
* this saves a useless scan of the hashtable during COMMIT or PREPARE.)
476-
*/
477-
xact_got_connection = false;
478483
}
479-
480484
/*
481485
* sqlitefdw_subxact_callback --- cleanup at subtransaction end.
482486
*/
@@ -538,15 +542,11 @@ sqlitefdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
538542
else
539543
{
540544
/* Rollback all remote subtransactions during abort */
541-
snprintf(sql, sizeof(sql),
542-
"ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d",
543-
curlevel, curlevel);
544-
if (!sqlite3_get_autocommit(entry->conn))
545-
sqlite_do_sql_command(entry->conn, sql, ERROR);
545+
sqlitefdw_abort_cleanup(entry, false);
546546
}
547547

548548
/* OK, we're outta that level of subtransaction */
549-
entry->xact_depth--;
549+
sqlitefdw_reset_xact_state(entry, false);
550550
}
551551
}
552552

@@ -628,13 +628,18 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
628628
#else
629629
#define SQLITE_FDW_GET_CONNECTIONS_COLS 2
630630
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
631+
HASH_SEQ_STATUS scan;
632+
ConnCacheEntry *entry;
633+
#if PG_VERSION_NUM < 150000
631634
TupleDesc tupdesc;
632635
Tuplestorestate *tupstore;
633636
MemoryContext per_query_ctx;
634637
MemoryContext oldcontext;
635-
HASH_SEQ_STATUS scan;
636-
ConnCacheEntry *entry;
638+
#endif
637639

640+
#if PG_VERSION_NUM >= 150000
641+
SetSingleFuncCall(fcinfo, 0);
642+
#else
638643
/* check to see if caller supports us returning a tuplestore */
639644
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
640645
ereport(ERROR,
@@ -659,12 +664,15 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
659664
rsinfo->setDesc = tupdesc;
660665

661666
MemoryContextSwitchTo(oldcontext);
667+
#endif
662668

663669
/* If cache doesn't exist, we return no records */
664670
if (!ConnectionHash)
665671
{
672+
#if PG_VERSION_NUM < 150000
666673
/* clean up and return the tuplestore */
667674
tuplestore_donestoring(tupstore);
675+
#endif
668676

669677
PG_RETURN_VOID();
670678
}
@@ -728,12 +736,17 @@ sqlite_fdw_get_connections(PG_FUNCTION_ARGS)
728736
values[0] = CStringGetTextDatum(server->servername);
729737

730738
values[1] = BoolGetDatum(!entry->invalidated);
731-
739+
#if PG_VERSION_NUM >= 150000
740+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
741+
#else
732742
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
743+
#endif
733744
}
734745

746+
#if PG_VERSION_NUM < 150000
735747
/* clean up and return the tuplestore */
736748
tuplestore_donestoring(tupstore);
749+
#endif
737750

738751
PG_RETURN_VOID();
739752
#endif
@@ -792,6 +805,41 @@ sqlite_fdw_disconnect_all(PG_FUNCTION_ARGS)
792805
#endif
793806
}
794807

808+
/*
809+
* Abort remote transaction or subtransaction.
810+
*
811+
* "toplevel" should be set to true if toplevel (main) transaction is
812+
* rollbacked, false otherwise.
813+
*/
814+
static void
815+
sqlitefdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel)
816+
{
817+
if (toplevel)
818+
{
819+
elog(DEBUG3, "abort transaction");
820+
821+
/* Finalize all prepared statements */
822+
sqlite_finalize_list_stmt(&entry->stmtList);
823+
824+
/*
825+
* rollback if in transaction because SQLite may
826+
* already rollback
827+
*/
828+
if (!sqlite3_get_autocommit(entry->conn))
829+
sqlite_do_sql_command(entry->conn, "ROLLBACK", WARNING);
830+
}
831+
else
832+
{
833+
char sql[100];
834+
int curlevel = GetCurrentTransactionNestLevel();
835+
snprintf(sql, sizeof(sql),
836+
"ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d",
837+
curlevel, curlevel);
838+
if (!sqlite3_get_autocommit(entry->conn))
839+
sqlite_do_sql_command(entry->conn, sql, ERROR);
840+
}
841+
}
842+
795843
#if PG_VERSION_NUM >= 140000
796844
/*
797845
* Workhorse to disconnect cached connections.

0 commit comments

Comments
 (0)