Some time ago I blogged on how to connect your PostgreSQL instance to an Oracle instance (here and here). In this post I’ll do the same with a MariaDB/MySQL instance.
For connecting PostgreSQL to MariaDB/Mysql we’ll need the foreign data wrapper for MySQL. As the foreign data wrapper for MySQL requires the MySQL/MariaDB client and development libraries lets install these first:
postgres@pgreporting:/home/postgres/ [pg952] sudo yum install -y mariadb-libs mariadb-devel
Make sure that you have mysql_config as well as pg_config in your PATH:
postgres@pgreporting:/home/postgres/ [pg952] which pg_config /u01/app/postgres/product/95/db_2/bin/pg_config postgres@pgreporting:/home/postgres/ [pg952] which mysql_config /usr/bin/mysql_config
Once you are ready it is straight forward:
postgres@pgreporting:/var/tmp/ [pg952] unzip mysql_fdw-master.zip postgres@pgreporting:/var/tmp/mysql_fdw-master/ [pg952] make USE_PGXS=1 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME="libmysqlclient.so" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o connection.o connection.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME="libmysqlclient.so" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o option.o option.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME="libmysqlclient.so" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o deparse.o deparse.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME="libmysqlclient.so" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o mysql_query.o mysql_query.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME="libmysqlclient.so" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o mysql_fdw.o mysql_fdw.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -shared -o mysql_fdw.so connection.o option.o deparse.o mysql_query.o mysql_fdw.o -L/u01/app/postgres/product/95/db_2/lib -Wl,--as-needed -Wl,-rpath,'/u01/app/postgres/product/95/db_2/lib',--enable-new-dtags postgres@pgreporting:/var/tmp/mysql_fdw-master/ [pg952] make USE_PGXS=1 install /bin/mkdir -p '/u01/app/postgres/product/95/db_2/lib' /bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension' /bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension' /bin/install -c -m 755 mysql_fdw.so '/u01/app/postgres/product/95/db_2/lib/mysql_fdw.so' /bin/install -c -m 644 .//mysql_fdw.control '/u01/app/postgres/product/95/db_2/share/extension/' /bin/install -c -m 644 .//mysql_fdw--1.0.sql '/u01/app/postgres/product/95/db_2/share/extension/'
From here on it is the usual steps. Create the extension:
postgres= create extension mysql_fdw; CREATE EXTENSION postgres= dx List of installed extensions Name | Version | Schema | Description -----------+---------+------------+-------------------------------------------------- mysql_fdw | 1.0 | public | Foreign data wrapper for querying a MySQL server plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (2 rows) postgres=
Make sure you are allowed to connect to your MySQL instance from where your PostgreSQL runs on. In my case I did this in the MariaDB instance:
MariaDB [DS2]> grant all on *.* TO 'web'@'192.168.22.39' identified by "web"; Query OK, 0 rows affected (0.00 sec) MariaDB [DS2]> SHOW GLOBAL VARIABLES LIKE 'PORT'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | port | 3306 | +---------------+-------+ 1 row in set (0.00 sec)
Once this is ready we can proceed on the PostgreSQL instance:
CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host '192.168.22.41', port '3306'); CREATE USER MAPPING FOR postgres SERVER mysql_server OPTIONS (username 'web', password 'web'); CREATE schema mysql; CREATE FOREIGN TABLE mysql.customer( CUSTOMERID bigint ,FIRSTNAME varchar(50) ,LASTNAME varchar(50) ,ADDRESS1 varchar(50) ,ADDRESS2 varchar(50) ,CITY varchar(50) ,STATE varchar(50) ,ZIP bigint ,COUNTRY varchar(50) ,REGION int ,EMAIL varchar(50) ,PHONE varchar(50) ,CREDITCARDTYPE bigint ,CREDITCARD varchar(50) ,CREDITCARDEXPIRATION varchar(50) ,USERNAME varchar(50) ,PASSWORD varchar(50) ,AGE int ,INCOME bigint ,GENDER varchar(1) ) SERVER mysql_server OPTIONS (dbname 'DS2', table_name 'CUSTOMERS'); postgres= select count(*) from mysql.customer; count -------- 200000 (1 row) postgres=#
If you wonder where the remote table comes from then have a look at the previous post where the schema is setup in the MariaDB/MySQL instance.
Even better, as with the oracle_fdw (if you are on PostgreSQL 9.5+), you can import the foreign schema:
postgres= import foreign schema "DS2" from server mysql_server into mysql; IMPORT FOREIGN SCHEMA postgres= show search_path; search_path ----------------- "$user", public (1 row) postgres= set search_path= 'mysql'; SET postgres= d List of relations Schema | Name | Type | Owner --------+------------+---------------+---------- mysql | CATEGORIES | foreign table | postgres mysql | CUSTOMERS | foreign table | postgres mysql | CUST_HIST | foreign table | postgres mysql | INVENTORY | foreign table | postgres mysql | ORDERLINES | foreign table | postgres mysql | ORDERS | foreign table | postgres mysql | PRODUCTS | foreign table | postgres mysql | REORDER | foreign table | postgres mysql | customer | foreign table | postgres (9 rows) postgres=# select count(*) from "ORDERS"; INFO: Successfully connected to MySQL database DS2 at server 192.168.22.41 via TCP/IP with cipher (server version: 5.5.47-MariaDB, protocol version: 10) count -------- 120000 (1 row)
One command and everything is there 🙂