Skip to content

Commit

Permalink
Merge pull request #13 from jopoly/RELEASE_v0.3.0
Browse files Browse the repository at this point in the history
RELEASE v0.3.0
  • Loading branch information
weiting1lee authored Jan 18, 2023
2 parents e1f3f6a + bf90a6c commit 8dfb093
Show file tree
Hide file tree
Showing 258 changed files with 74,972 additions and 3,311 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ JDBC Foreign Data Wrapper for PostgreSQL

**jdbc_fdw** is released under the PostgreSQL License, a liberal Open Source license, similar to the BSD or MIT licenses.

Portions Copyright (c) 2021, TOSHIBA CORPORATION
Copyright (c) 2021, TOSHIBA CORPORATION

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.

Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
JDBC Foreign Data Wrapper for PostgreSQL
=========================================
* This PostgreSQL extension is a Foreign Data Wrapper (FDW) for JDBC.
* The current version can work with PostgreSQL 13, 14.
* The current version can work with PostgreSQL 14.
* Java 5 or later is required (Confirmed version is Java OpenJDK 1.8.0).
* This jdbc_fdw is based on [JDBC\_FDW](http://github.com/atris/JDBC_FDW.git), [jdbc2\_fdw](https://github.com/heimir-sverrisson/jdbc2_fdw).

Expand Down Expand Up @@ -182,6 +182,23 @@ SELECT float4.f1 FROM tbl06 float4 WHERE float4.f1 <> '1004.3' GROUP BY float4.i
(4 rows)
```

#### IMPORT FOREIGN SCHEMA
Currently, IMPORT FOREIGN SCHEMA works only with GridDB.

Usage Notes
-----------
#### Maximum digits storing float value of MySQL
Maximum digits storing float value of MySQL is 6 digits. The stored value may not be the same as the value inserted.

#### Variance function
Variance function: For MySQL, variance function is alias for var_pop(). For PostgreSQL/GridDB, variance function is alias for var_samp(). Due to the different meaning of variance function between MySQL and PostgreSQL/GridDB, the result will be different.

#### Concatenation Operator
The || operator as a concatenation operator is standard SQL, however in MySQL, it represents the OR operator (logical operator). If the PIPES_AS_CONCAT SQL mode is enabled, || signifies the SQL-standard string concatenation operator (like CONCAT()). User needs to enable PIPES_AS_CONCAT mode in MySQL for concatenation.

#### Timestamp range
The MySQL timestamp range is not the same as the PostgreSQL timestamp range, so be careful if using this type. In MySQL, TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

Reference
---------
[JDBC\_FDW](http://github.com/atris/JDBC_FDW.git)
Expand Down
171 changes: 110 additions & 61 deletions connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,23 @@ typedef struct ConnCacheEntry
static HTAB *ConnectionHash = NULL;

/* for assigning cursor numbers and prepared statement numbers */
static unsigned int cursor_number = 0;
static volatile unsigned int cursor_number = 0;
static unsigned int prep_stmt_number = 0;

/* tracks whether any work is needed in callback functions */
static bool xact_got_connection = false;
static volatile bool xact_got_connection = false;

/* prototypes of private functions */
static Jconn * connect_jdbc_server(ForeignServer *server, UserMapping *user);
static void jdbc_check_conn_params(const char **keywords, const char **values);
static void jdbc_do_sql_command(Jconn * conn, const char *sql);
static void jdbcfdw_xact_callback(XactEvent event, void *arg);
static void jdbcfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel);
static void jdbcfdw_subxact_callback(SubXactEvent event,
SubTransactionId mySubid,
SubTransactionId parentSubid,
void *arg);
static void jdbcfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel);


/*
Expand Down Expand Up @@ -168,6 +170,10 @@ jdbc_get_connection(ForeignServer *server, UserMapping *user,
entry->have_error = false;
entry->conn = connect_jdbc_server(server, user);
}
else
{
jdbc_jvm_init(server, user);
}

/* Remember if caller will prepare statements */
entry->have_prep_stmt |= will_prep_stmt;
Expand Down Expand Up @@ -513,39 +519,10 @@ jdbcfdw_xact_callback(XactEvent event, void *arg)
elog(ERROR, "missed cleaning up connection during pre-commit");
break;
case XACT_EVENT_ABORT:

/*
* Assume we might have lost track of prepared statements
*/
entry->have_error = true;

/*
* If we're aborting, abort all remote transactions too
*/
res = jq_exec(entry->conn, "ABORT TRANSACTION");

/*
* Note: can't throw ERROR, it would be infinite loop
*/
if (*res != PGRES_COMMAND_OK)
jdbc_fdw_report_error(WARNING, res, entry->conn, true,
"ABORT TRANSACTION");
else
{
jq_clear(res);

/*
* As above, make sure to clear any prepared stmts
*/
if (entry->have_prep_stmt && entry->have_error)
{
res = jq_exec(entry->conn, "DEALLOCATE ALL");
jq_clear(res);
}
entry->have_prep_stmt = false;
entry->have_error = false;
}
{
jdbcfdw_abort_cleanup(entry, true);
break;
}
case XACT_EVENT_PARALLEL_COMMIT:
break;
case XACT_EVENT_PARALLEL_ABORT:
Expand All @@ -556,19 +533,7 @@ jdbcfdw_xact_callback(XactEvent event, void *arg)
}

/* Reset state to show we're out of a transaction */
entry->xact_depth = 0;

/*
* If the connection isn't in a good idle state, discard it to
* recover. Next GetConnection will open a new connection.
*/
if (jq_status(entry->conn) != CONNECTION_OK ||
jq_transaction_status(entry->conn) != PQTRANS_IDLE)
{
elog(DEBUG3, "discarding connection %p", entry->conn);
jq_finish(entry->conn);
entry->conn = NULL;
}
jdbcfdw_reset_xact_state(entry, true);
}

/*
Expand All @@ -582,6 +547,75 @@ jdbcfdw_xact_callback(XactEvent event, void *arg)
cursor_number = 0;
}

/*
* Abort remote transaction or subtransaction.
*
* "toplevel" should be set to true if toplevel (main) transaction is
* rollbacked, false otherwise.
*
* Set entry->changing_xact_state to false on success, true on failure.
*/
static void
jdbcfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel)
{
Jresult *res;

if (toplevel)
{
/*
* Assume we might have lost track of prepared statements
*/
entry->have_error = true;

/*
* If we're aborting, abort all remote transactions too
*/
res = jq_exec(entry->conn, "ABORT TRANSACTION");

/*
* Note: can't throw ERROR, it would be infinite loop
*/
if (*res != PGRES_COMMAND_OK)
jdbc_fdw_report_error(WARNING, res, entry->conn, true,
"ABORT TRANSACTION");
else
{
jq_clear(res);

/*
* As above, make sure to clear any prepared stmts
*/
if (entry->have_prep_stmt && entry->have_error)
{
res = jq_exec(entry->conn, "DEALLOCATE ALL");
jq_clear(res);
}
entry->have_prep_stmt = false;
entry->have_error = false;
}
}
else
{
char sql[100];
int curlevel = GetCurrentTransactionNestLevel();

/*
* Assume we might have lost track of prepared statements
*/
entry->have_error = true;

/* Rollback all remote subtransactions during abort */
snprintf(sql, sizeof(sql),
"ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d",
curlevel, curlevel);
res = jq_exec(entry->conn, sql);
if (*res != PGRES_COMMAND_OK)
jdbc_fdw_report_error(WARNING, res, entry->conn, true, sql);
else
jq_clear(res);
}
}

/*
* jdbcfdw_subxact_callback --- cleanup at subtransaction end.
*/
Expand Down Expand Up @@ -610,7 +644,6 @@ jdbcfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
hash_seq_init(&scan, ConnectionHash);
while ((entry = (ConnCacheEntry *) hash_seq_search(&scan)))
{
Jresult *res;
char sql[100];

/*
Expand All @@ -634,22 +667,38 @@ jdbcfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
}
else
{
/*
* Assume we might have lost track of prepared statements
*/
entry->have_error = true;
/* Rollback all remote subtransactions during abort */
snprintf(sql, sizeof(sql),
"ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d",
curlevel, curlevel);
res = jq_exec(entry->conn, sql);
if (*res != PGRES_COMMAND_OK)
jdbc_fdw_report_error(WARNING, res, entry->conn, true, sql);
else
jq_clear(res);
jdbcfdw_abort_cleanup(entry, false);
}

/* OK, we're outta that level of subtransaction */
jdbcfdw_reset_xact_state(entry, false);
}
}

/*
* jdbcfdw_reset_xact_state --- Reset state to show we're out of a (sub)transaction
*/
static void
jdbcfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel)
{
if (toplevel)
{
entry->xact_depth = 0;

/*
* If the connection isn't in a good idle state, discard it to
* recover. Next GetConnection will open a new connection.
*/
if (jq_status(entry->conn) != CONNECTION_OK ||
jq_transaction_status(entry->conn) != PQTRANS_IDLE)
{
elog(DEBUG3, "discarding connection %p", entry->conn);
jq_finish(entry->conn);
entry->conn = NULL;
}
}
else
{
entry->xact_depth--;
}
}
2 changes: 1 addition & 1 deletion deparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ jdbc_deparse_select_stmt_for_rel(StringInfo buf,
static bool
jdbc_is_builtin(Oid oid)
{
return (oid < FirstBootstrapObjectId);
return (oid < FirstGenbkiObjectId);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-- AGGREGATES
--
\set ECHO none
\i sql/13.4/aggregates.sql
\i sql/13.8/aggregates.sql
--
-- AGGREGATES
--
Expand Down Expand Up @@ -533,7 +533,7 @@ FROM regr_test WHERE x IN (10,20,30,80);
--Testcase 64:
SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
FROM regr_test WHERE x IN (10,20,30,80);
psql:sql/13.4/aggregates.sql:186: ERROR: remote server returned an error
psql:sql/13.8/aggregates.sql:186: ERROR: remote server returned an error
--Testcase 65:
EXPLAIN VERBOSE SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) FROM regr_test;
QUERY PLAN
Expand Down Expand Up @@ -567,7 +567,7 @@ FROM regr_test WHERE x IN (10,20,30);
--Testcase 68:
SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
FROM regr_test WHERE x IN (10,20,30);
psql:sql/13.4/aggregates.sql:196: ERROR: remote server returned an error
psql:sql/13.8/aggregates.sql:196: ERROR: remote server returned an error
--Testcase 69:
EXPLAIN VERBOSE SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
FROM regr_test WHERE x IN (80,100);
Expand All @@ -583,7 +583,7 @@ FROM regr_test WHERE x IN (80,100);
--Testcase 70:
SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
FROM regr_test WHERE x IN (80,100);
psql:sql/13.4/aggregates.sql:202: ERROR: remote server returned an error
psql:sql/13.8/aggregates.sql:202: ERROR: remote server returned an error
--Testcase 71:
DROP FOREIGN TABLE regr_test;
-- test count, distinct
Expand Down Expand Up @@ -887,22 +887,22 @@ select max(100) from tenk1;
-- check for correct detection of nested-aggregate errors
--Testcase 101:
EXPLAIN VERBOSE select max(min(unique1)) from tenk1;
psql:sql/13.4/aggregates.sql:351: ERROR: aggregate function calls cannot be nested
psql:sql/13.8/aggregates.sql:351: ERROR: aggregate function calls cannot be nested
LINE 1: EXPLAIN VERBOSE select max(min(unique1)) from tenk1;
^
--Testcase 102:
select max(min(unique1)) from tenk1;
psql:sql/13.4/aggregates.sql:353: ERROR: aggregate function calls cannot be nested
psql:sql/13.8/aggregates.sql:353: ERROR: aggregate function calls cannot be nested
LINE 1: select max(min(unique1)) from tenk1;
^
--Testcase 103:
EXPLAIN VERBOSE select (select max(min(unique1)) from int8_tbl) from tenk1;
psql:sql/13.4/aggregates.sql:355: ERROR: aggregate function calls cannot be nested
psql:sql/13.8/aggregates.sql:355: ERROR: aggregate function calls cannot be nested
LINE 1: EXPLAIN VERBOSE select (select max(min(unique1)) from int8_t...
^
--Testcase 104:
select (select max(min(unique1)) from int8_tbl) from tenk1;
psql:sql/13.4/aggregates.sql:357: ERROR: aggregate function calls cannot be nested
psql:sql/13.8/aggregates.sql:357: ERROR: aggregate function calls cannot be nested
LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1;
^
--
Expand Down Expand Up @@ -979,7 +979,7 @@ EXPLAIN VERBOSE select pg_get_viewdef('agg_view1'::regclass);
QUERY PLAN
-------------------------------------------
Result (cost=0.00..0.01 rows=1 width=32)
Output: pg_get_viewdef('16453'::oid)
Output: pg_get_viewdef('16461'::oid)
(2 rows)

--Testcase 115:
Expand Down Expand Up @@ -1023,7 +1023,7 @@ EXPLAIN VERBOSE select pg_get_viewdef('agg_view1'::regclass);
QUERY PLAN
-------------------------------------------
Result (cost=0.00..0.01 rows=1 width=32)
Output: pg_get_viewdef('16453'::oid)
Output: pg_get_viewdef('16461'::oid)
(2 rows)

--Testcase 120:
Expand Down Expand Up @@ -1526,15 +1526,15 @@ explain (costs off)

--Testcase 207:
DROP TYPE aggtype CASCADE;
psql:sql/13.4/aggregates.sql:639: NOTICE: drop cascades to 2 other objects
psql:sql/13.8/aggregates.sql:639: NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to function aggfns_trans(aggtype[],integer,integer,text)
drop cascades to function aggfns(integer,integer,text)
--Testcase 208:
DROP FUNCTION cleast_accum CASCADE;
psql:sql/13.4/aggregates.sql:641: NOTICE: drop cascades to function cleast_agg(anycompatiblearray)
psql:sql/13.8/aggregates.sql:641: NOTICE: drop cascades to function cleast_agg(anycompatiblearray)
--Testcase 177:
DROP SERVER :DB_SERVERNAME CASCADE;
psql:sql/13.4/aggregates.sql:643: NOTICE: drop cascades to 13 other objects
psql:sql/13.8/aggregates.sql:643: NOTICE: drop cascades to 13 other objects
DETAIL: drop cascades to user mapping for public on server griddb_server
drop cascades to foreign table onek
drop cascades to foreign table aggtest
Expand Down
Loading

0 comments on commit 8dfb093

Please sign in to comment.