Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

pkgs = nixpkgs.legacyPackages.${system};

# PostgreSQL 18 isn't released yet, and therefore isn't available in nixpkgs. As a temporary pre-release measure,
# override the PG17 package with the beta release tag and version to build the beta.
postgresql_18 = (pkgs.postgresql_17.override {
version = "18.0";
rev = "refs/tags/REL_18_BETA1";
hash = "sha256-P86bVYfPzkwK/rcvUInYZew/pKejk58/IcnDGx/BWno=";
});

requiredPythonPackages = ps: (
# Such that we pass the UNSUPPORTS_SQLALCHEMY check in Makefile and can run the SQLAlchemy tests
[ ps.sqlalchemy ] ++ ps.sqlalchemy.optional-dependencies.postgresql
Expand All @@ -34,6 +42,7 @@
postgresql_15
postgresql_16
postgresql_17
postgresql_18
];
testVersionCombos = pkgs.lib.cartesianProduct {
python = testPythonVersions;
Expand Down
9 changes: 9 additions & 0 deletions src/multicorn.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "parser/parsetree.h"
#include "fmgr.h"
#include "common/hashfn.h" /* oid_hash */
#if PG_VERSION_NUM >= 180000
#include "commands/explain_format.h"
#endif


PG_MODULE_MAGIC;
Expand Down Expand Up @@ -361,6 +364,9 @@ multicornGetForeignPaths(PlannerInfo *root,
pathes = lappend(pathes, create_foreignscan_path(root, baserel,
NULL, /* default pathtarget */
baserel->rows,
#if PG_VERSION_NUM >= 180000 // # of disabled_nodes added in PG 18, commit e22253467942fdb100087787c3e1e3a8620c54b2
0,
#endif
planstate->startupCost,
baserel->rows * baserel->reltarget->width,
NIL, /* no pathkeys */
Expand Down Expand Up @@ -400,6 +406,9 @@ multicornGetForeignPaths(PlannerInfo *root,
newpath = create_foreignscan_path(root, baserel,
NULL, /* default pathtarget */
path->path.rows,
#if PG_VERSION_NUM >= 180000 // # of disabled_nodes added in PG 18, commit e22253467942fdb100087787c3e1e3a8620c54b2
0,
#endif
path->path.startup_cost, path->path.total_cost,
apply_pathkeys, NULL,
NULL,
Expand Down
3 changes: 3 additions & 0 deletions src/multicorn.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/explain.h"
#if PG_VERSION_NUM >= 180000
#include "commands/explain_state.h"
#endif
#include "foreign/fdwapi.h"
#include "foreign/foreign.h"
#include "funcapi.h"
Expand Down
7 changes: 7 additions & 0 deletions src/query.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,9 @@ findPaths(PlannerInfo *root, RelOptInfo *baserel, List *possiblePaths,
root, baserel,
NULL, /* default pathtarget */
nbrows,
#if PG_VERSION_NUM >= 180000 // # of disabled_nodes added in PG 18, commit e22253467942fdb100087787c3e1e3a8620c54b2
0,
#endif
startupCost,
nbrows * baserel->reltarget->width,
NIL, /* no pathkeys */
Expand Down Expand Up @@ -757,7 +760,11 @@ deparse_sortgroup(PlannerInfo *root, Oid foreigntableid, RelOptInfo *rel)

if ((expr = multicorn_get_em_expr(ec, rel)))
{
#if PG_VERSION_NUM >= 180000 // pk_strategy replaced w/ pkg_cmptype in PG 18, commit 8123e91f5aeb26c6e4cf583bb61c99281485af83
md->reversed = (key->pk_cmptype == COMPARE_GT);
#else
md->reversed = (key->pk_strategy == BTGreaterStrategyNumber);
#endif
md->nulls_first = key->pk_nulls_first;
md->key = key;

Expand Down
190 changes: 190 additions & 0 deletions test-3.9/expected/write_test_4.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
CREATE EXTENSION multicorn;
CREATE server multicorn_srv foreign data wrapper multicorn options (
wrapper 'multicorn.testfdw.TestForeignDataWrapper'
);
CREATE user mapping FOR current_user server multicorn_srv options (usermapping 'test');
CREATE foreign table testmulticorn (
test1 character varying,
test2 character varying
) server multicorn_srv options (
option1 'option1',
test_type 'nowrite',
tx_hook 'true'
);
insert into testmulticorn(test1, test2) VALUES ('test', 'test2');
NOTICE: [('option1', 'option1'), ('test_type', 'nowrite'), ('tx_hook', 'true'), ('usermapping', 'test')]
NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
NOTICE: BEGIN
NOTICE: ROLLBACK
ERROR: Error in python: NotImplementedError
DETAIL: This FDW does not support the writable API
update testmulticorn set test1 = 'test';
NOTICE: BEGIN
NOTICE: []
NOTICE: ['test1', 'test2']
ERROR: Error in python: NotImplementedError
DETAIL: This FDW does not support the writable API
NOTICE: ROLLBACK
delete from testmulticorn where test2 = 'test2 2 0';
NOTICE: BEGIN
NOTICE: [test2 = test2 2 0]
NOTICE: ['test1', 'test2']
ERROR: Error in python: NotImplementedError
DETAIL: This FDW does not support the writable API
NOTICE: ROLLBACK
CREATE foreign table testmulticorn_write (
test1 character varying,
test2 character varying
) server multicorn_srv options (
option1 'option1',
row_id_column 'test1',
test_type 'returning',
tx_hook 'true'
);
insert into testmulticorn_write(test1, test2) VALUES ('test', 'test2');
NOTICE: [('option1', 'option1'), ('row_id_column', 'test1'), ('test_type', 'returning'), ('tx_hook', 'true'), ('usermapping', 'test')]
NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
NOTICE: BEGIN
NOTICE: INSERTING: [('test1', 'test'), ('test2', 'test2')]
NOTICE: PRECOMMIT
NOTICE: COMMIT
update testmulticorn_write set test1 = 'test' where test1 ilike 'test1 3%';
NOTICE: BEGIN
NOTICE: [test1 ~~* test1 3%]
NOTICE: ['test1', 'test2']
NOTICE: UPDATING: test1 3 1 with [('test1', 'test'), ('test2', 'test2 1 1')]
NOTICE: UPDATING: test1 3 4 with [('test1', 'test'), ('test2', 'test2 1 4')]
NOTICE: UPDATING: test1 3 7 with [('test1', 'test'), ('test2', 'test2 1 7')]
NOTICE: UPDATING: test1 3 10 with [('test1', 'test'), ('test2', 'test2 1 10')]
NOTICE: UPDATING: test1 3 13 with [('test1', 'test'), ('test2', 'test2 1 13')]
NOTICE: UPDATING: test1 3 16 with [('test1', 'test'), ('test2', 'test2 1 16')]
NOTICE: UPDATING: test1 3 19 with [('test1', 'test'), ('test2', 'test2 1 19')]
NOTICE: PRECOMMIT
NOTICE: COMMIT
delete from testmulticorn_write where test2 = 'test2 2 0';
NOTICE: BEGIN
NOTICE: [test2 = test2 2 0]
NOTICE: ['test1', 'test2']
NOTICE: DELETING: test1 1 0
NOTICE: PRECOMMIT
NOTICE: COMMIT
-- Test returning
insert into testmulticorn_write(test1, test2) VALUES ('test', 'test2') RETURNING test1;
NOTICE: BEGIN
NOTICE: INSERTING: [('test1', 'test'), ('test2', 'test2')]
NOTICE: PRECOMMIT
NOTICE: COMMIT
test1
----------------
INSERTED: test
(1 row)

update testmulticorn_write set test1 = 'test' where test1 ilike 'test1 3%' RETURNING test1;
NOTICE: BEGIN
NOTICE: [test1 ~~* test1 3%]
NOTICE: ['test1', 'test2']
NOTICE: UPDATING: test1 3 1 with [('test1', 'test'), ('test2', 'test2 1 1')]
NOTICE: UPDATING: test1 3 4 with [('test1', 'test'), ('test2', 'test2 1 4')]
NOTICE: UPDATING: test1 3 7 with [('test1', 'test'), ('test2', 'test2 1 7')]
NOTICE: UPDATING: test1 3 10 with [('test1', 'test'), ('test2', 'test2 1 10')]
NOTICE: UPDATING: test1 3 13 with [('test1', 'test'), ('test2', 'test2 1 13')]
NOTICE: UPDATING: test1 3 16 with [('test1', 'test'), ('test2', 'test2 1 16')]
NOTICE: UPDATING: test1 3 19 with [('test1', 'test'), ('test2', 'test2 1 19')]
NOTICE: PRECOMMIT
NOTICE: COMMIT
test1
---------------
UPDATED: test
UPDATED: test
UPDATED: test
UPDATED: test
UPDATED: test
UPDATED: test
UPDATED: test
(7 rows)

delete from testmulticorn_write where test1 = 'test1 1 0' returning test2, test1;
NOTICE: BEGIN
NOTICE: [test1 = test1 1 0]
NOTICE: ['test1', 'test2']
NOTICE: DELETING: test1 1 0
NOTICE: PRECOMMIT
NOTICE: COMMIT
test2 | test1
-----------+-----------
test2 2 0 | test1 1 0
(1 row)

DROP foreign table testmulticorn_write;
-- Now test with another column
CREATE foreign table testmulticorn_write(
test1 character varying,
test2 character varying
) server multicorn_srv options (
option1 'option1',
row_id_column 'test2'
);
insert into testmulticorn_write(test1, test2) VALUES ('test', 'test2');
NOTICE: [('option1', 'option1'), ('row_id_column', 'test2'), ('usermapping', 'test')]
NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
NOTICE: INSERTING: [('test1', 'test'), ('test2', 'test2')]
update testmulticorn_write set test1 = 'test' where test1 ilike 'test1 3%';
NOTICE: [test1 ~~* test1 3%]
NOTICE: ['test1', 'test2']
NOTICE: UPDATING: test2 1 1 with [('test1', 'test'), ('test2', 'test2 1 1')]
NOTICE: UPDATING: test2 1 4 with [('test1', 'test'), ('test2', 'test2 1 4')]
NOTICE: UPDATING: test2 1 7 with [('test1', 'test'), ('test2', 'test2 1 7')]
NOTICE: UPDATING: test2 1 10 with [('test1', 'test'), ('test2', 'test2 1 10')]
NOTICE: UPDATING: test2 1 13 with [('test1', 'test'), ('test2', 'test2 1 13')]
NOTICE: UPDATING: test2 1 16 with [('test1', 'test'), ('test2', 'test2 1 16')]
NOTICE: UPDATING: test2 1 19 with [('test1', 'test'), ('test2', 'test2 1 19')]
delete from testmulticorn_write where test2 = 'test2 2 0';
NOTICE: [test2 = test2 2 0]
NOTICE: ['test2']
NOTICE: DELETING: test2 2 0
update testmulticorn_write set test2 = 'test' where test2 = 'test2 1 1';
NOTICE: [test2 = test2 1 1]
NOTICE: ['test1', 'test2']
NOTICE: UPDATING: test2 1 1 with [('test1', 'test1 3 1'), ('test2', 'test')]
DROP foreign table testmulticorn_write;
-- Now test with other types
CREATE foreign table testmulticorn_write(
test1 date,
test2 timestamp
) server multicorn_srv options (
option1 'option1',
row_id_column 'test2',
test_type 'date'
);
insert into testmulticorn_write(test1, test2) VALUES ('2012-01-01', '2012-01-01 00:00:00');
NOTICE: [('option1', 'option1'), ('row_id_column', 'test2'), ('test_type', 'date'), ('usermapping', 'test')]
NOTICE: [('test1', 'date'), ('test2', 'timestamp without time zone')]
NOTICE: INSERTING: [('test1', datetime.date(2012, 1, 1)), ('test2', datetime.datetime(2012, 1, 1, 0, 0))]
delete from testmulticorn_write where test2 > '2011-12-03';
NOTICE: [test2 > 2011-12-03 00:00:00]
NOTICE: ['test2']
NOTICE: DELETING: 2011-12-03 14:30:25
update testmulticorn_write set test1 = date_trunc('day', test1) where test2 = '2011-09-03 14:30:25';
NOTICE: [test2 = 2011-09-03 14:30:25]
NOTICE: ['test1', 'test2']
NOTICE: UPDATING: 2011-09-03 14:30:25 with [('test1', datetime.date(2011, 9, 2)), ('test2', datetime.datetime(2011, 9, 3, 14, 30, 25))]
DROP foreign table testmulticorn_write;
-- Test with unknown column
CREATE foreign table testmulticorn_write(
test1 date,
test2 timestamp
) server multicorn_srv options (
option1 'option1',
row_id_column 'teststuff',
test_type 'date'
);
delete from testmulticorn_write;
NOTICE: [('option1', 'option1'), ('row_id_column', 'teststuff'), ('test_type', 'date'), ('usermapping', 'test')]
NOTICE: [('test1', 'date'), ('test2', 'timestamp without time zone')]
ERROR: The rowid attribute does not exist
DROP USER MAPPING FOR current_user SERVER multicorn_srv;
DROP EXTENSION multicorn cascade;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to server multicorn_srv
drop cascades to foreign table testmulticorn
drop cascades to foreign table testmulticorn_write
Loading