Skip to content
multicorn

multicorn

multicorn : Fetch foreign data in Python in your PostgreSQL server.

Overview

ID Extension Package Version Category License Language
8510
multicorn
multicorn
3.2
FDW
PostgreSQL
C
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--s-d--
No
Yes
No
Yes
no
no
Relationships
See Also
wrappers
odbc_fdw
jdbc_fdw
pgspider_ext
mysql_fdw
db2_fdw
mongo_fdw
redis_fdw

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT
PGDG
3.2
18
17
16
15
14
multicorn -
RPM
PGDG
3.2
18
17
16
15
14
multicorn2_$v -
DEB
PIGSTY
3.2
18
17
16
15
14
postgresql-$v-multicorn python3-multicorn
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
el8.aarch64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
el9.x86_64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
el9.aarch64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
el10.x86_64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
el10.aarch64
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
PGDG 3.2
d12.x86_64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
d12.aarch64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
d13.x86_64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
d13.aarch64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u22.x86_64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u22.aarch64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u24.x86_64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u24.aarch64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u26.x86_64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
u26.aarch64
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
PIGSTY 3.2
Package Version OS ORG SIZE File URL
multicorn2_18 3.2 el8.x86_64 pgdg 138.0 KiB multicorn2_18-3.2-1PGDG.rhel8.x86_64.rpm
multicorn2_18 3.1 el8.x86_64 pgdg 135.5 KiB multicorn2_18-3.1-1PGDG.rhel8.x86_64.rpm
multicorn2_18 3.2 el8.aarch64 pgdg 136.3 KiB multicorn2_18-3.2-1PGDG.rhel8.aarch64.rpm
multicorn2_18 3.1 el8.aarch64 pgdg 133.9 KiB multicorn2_18-3.1-1PGDG.rhel8.aarch64.rpm
multicorn2_18 3.2 el9.x86_64 pgdg 134.6 KiB multicorn2_18-3.2-3PGDG.rhel9.8.x86_64.rpm
multicorn2_18 3.2 el9.x86_64 pgdg 134.6 KiB multicorn2_18-3.2-1PGDG.rhel9.x86_64.rpm
multicorn2_18 3.1 el9.x86_64 pgdg 111.0 KiB multicorn2_18-3.1-1PGDG.rhel9.x86_64.rpm
multicorn2_18 3.2 el9.aarch64 pgdg 133.8 KiB multicorn2_18-3.2-3PGDG.rhel9.8.aarch64.rpm
multicorn2_18 3.2 el9.aarch64 pgdg 133.5 KiB multicorn2_18-3.2-1PGDG.rhel9.aarch64.rpm
multicorn2_18 3.1 el9.aarch64 pgdg 110.0 KiB multicorn2_18-3.1-1PGDG.rhel9.aarch64.rpm
multicorn2_18 3.2 el10.x86_64 pgdg 135.2 KiB multicorn2_18-3.2-3PGDG.rhel10.2.x86_64.rpm
multicorn2_18 3.2 el10.x86_64 pgdg 135.5 KiB multicorn2_18-3.2-1PGDG.rhel10.x86_64.rpm
multicorn2_18 3.1 el10.x86_64 pgdg 133.0 KiB multicorn2_18-3.1-1PGDG.rhel10.x86_64.rpm
multicorn2_18 3.2 el10.aarch64 pgdg 134.4 KiB multicorn2_18-3.2-3PGDG.rhel10.2.aarch64.rpm
multicorn2_18 3.2 el10.aarch64 pgdg 134.6 KiB multicorn2_18-3.2-1PGDG.rhel10.aarch64.rpm
multicorn2_18 3.1 el10.aarch64 pgdg 131.9 KiB multicorn2_18-3.1-1PGDG.rhel10.aarch64.rpm
postgresql-18-multicorn 3.2 d12.x86_64 pigsty 81.5 KiB postgresql-18-multicorn_3.2-1PIGSTY~bookworm_amd64.deb
postgresql-18-multicorn 3.2 d12.aarch64 pigsty 79.7 KiB postgresql-18-multicorn_3.2-1PIGSTY~bookworm_arm64.deb
postgresql-18-multicorn 3.2 d13.x86_64 pigsty 82.5 KiB postgresql-18-multicorn_3.2-1PIGSTY~trixie_amd64.deb
postgresql-18-multicorn 3.2 d13.aarch64 pigsty 80.8 KiB postgresql-18-multicorn_3.2-1PIGSTY~trixie_arm64.deb
postgresql-18-multicorn 3.2 u22.x86_64 pigsty 87.7 KiB postgresql-18-multicorn_3.2-1PIGSTY~jammy_amd64.deb
postgresql-18-multicorn 3.2 u22.aarch64 pigsty 86.9 KiB postgresql-18-multicorn_3.2-1PIGSTY~jammy_arm64.deb
postgresql-18-multicorn 3.2 u24.x86_64 pigsty 85.5 KiB postgresql-18-multicorn_3.2-1PIGSTY~noble_amd64.deb
postgresql-18-multicorn 3.2 u24.aarch64 pigsty 84.3 KiB postgresql-18-multicorn_3.2-1PIGSTY~noble_arm64.deb
postgresql-18-multicorn 3.2 u26.x86_64 pigsty 84.8 KiB postgresql-18-multicorn_3.2-1PIGSTY~resolute_amd64.deb
postgresql-18-multicorn 3.2 u26.aarch64 pigsty 83.7 KiB postgresql-18-multicorn_3.2-1PIGSTY~resolute_arm64.deb

Source

Install

Make sure PGDG repo available:

pig repo add pgdg -u    # add pgdg repo and update cache

Install this extension with pig:

pig install multicorn;		# install via package name, for the active PG version

pig install multicorn -v 18;   # install for PG 18
pig install multicorn -v 17;   # install for PG 17
pig install multicorn -v 16;   # install for PG 16
pig install multicorn -v 15;   # install for PG 15
pig install multicorn -v 14;   # install for PG 14

Create this extension with:

CREATE EXTENSION multicorn;

Usage

Sources: README, CHANGELOG

Multicorn2 allows you to write Foreign Data Wrappers in Python. You implement a Python class that inherits from multicorn.ForeignDataWrapper, and Multicorn handles bridging it to PostgreSQL’s FDW interface. Version 3.2 is tested with PostgreSQL 14-18 and Python 3.9-3.13, though upstream recommends Python 3.10-3.12 for near-term distro compatibility.

Define a Python FDW Class

Create a Python module (e.g., myfdw.py) accessible to the PostgreSQL process:

from multicorn import ForeignDataWrapper

class MyFDW(ForeignDataWrapper):
    def __init__(self, options, columns):
        super().__init__(options, columns)
        self.options = options
        self.columns = columns

    def execute(self, quals, columns):
        """Yield rows as dictionaries. quals contains WHERE pushdown info."""
        yield {"id": 1, "name": "example"}

    def insert(self, new_values):
        """Handle INSERT operations."""
        pass

    def update(self, old_values, new_values):
        """Handle UPDATE operations."""
        pass

    def delete(self, old_values):
        """Handle DELETE operations."""
        pass

Create Server and Foreign Table

CREATE EXTENSION multicorn;

CREATE SERVER multicorn_srv FOREIGN DATA WRAPPER multicorn
  OPTIONS (wrapper 'myfdw.MyFDW');

CREATE FOREIGN TABLE my_table (
  id integer,
  name text
)
SERVER multicorn_srv
OPTIONS (
  option1 'value1'
);

SELECT * FROM my_table;

The wrapper option specifies the fully qualified Python class name. Any additional options are passed to the class constructor’s options parameter.

Built-in FDW Examples

Multicorn ships with several example FDW implementations that can be used directly or as reference:

  • CsvFdw – read CSV files
  • ProcessFdw – execute system commands and parse output
  • GCalFdw – access Google Calendar
  • ImapFdw – query IMAP mailboxes
  • RssFdw – read RSS/Atom feeds
CREATE SERVER csv_srv FOREIGN DATA WRAPPER multicorn
  OPTIONS (wrapper 'multicorn.csvfdw.CsvFdw');

CREATE FOREIGN TABLE csvtest (
  col1 text,
  col2 text
)
SERVER csv_srv
OPTIONS (
  filename '/tmp/data.csv',
  skip_header '1',
  delimiter ','
);

Version Notes

Multicorn 3.2 adds basic OFFSET/LIMIT pushdown and LDAP paging support, and fixes LDAP right-parenthesis escaping. Upstream 3.1 added PostgreSQL 18 and Python 3.13 support while dropping PostgreSQL versions before 14.

Caveats

Multicorn2 and PL/Python are incompatible in the same PostgreSQL database on Python 3.12 due to CPython limitations. They can be installed on the same system, but avoid enabling both in one database.

Last updated on