Up to Postgres 9.2, the only foreign data wrapper present in core was file_fdw, allowing you to query files as remote tables. This has been corrected with the addition of a second foreign data wrapper called postgres_fdw. This one simply allows to query foreign Postgres servers and fetch results directly on your local server. It has been introduced by this commit.
commit d0d75c402217421b691050857eb3d7af82d0c770
Author: Tom Lane
Date: Thu Feb 21 05:26:23 2013 -0500
 
Add postgres_fdw contrib module.
 
There's still a lot of room for improvement, but it basically works,
and we need this to be present before we can do anything much with the
writable-foreign-tables patch. So let's commit it and get on with testing.
 
Shigeru Hanada, reviewed by KaiGai Kohei and Tom Lane

Documentation can be found here for the time being.

In order to install it from source, do the following commands from the Postgres root folder.
cd contrib/postgres_fdw
make install

Then connect to your existing Postgres server and finish the installation with CREATE EXTENSION.
postgres=# CREATE EXTENSION postgres_fdw;
CREATE EXTENSION
postgres=# \dx postgres_fdw
List of installed extensions
Name | Version | Schema | Description
--------------+---------+--------+----------------------------------------------------
postgres_fdw | 1.0 | public | foreign-data wrapper for remote PostgreSQL servers
(1 row)

Now let’s test it with the case of a simple cluster with one slave running with port 5532 on the same server as its master. Here is the configuration.
$ psql -p 5532 -c 'select pg_is_in_recovery()'
pg_is_in_recovery
-------------------
t
(1 row)

When using a foreign data wrapper, you need to create first a server.
postgres=# CREATE SERVER postgres_server
postgres=# FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost', port '5532', dbname 'postgres');
CREATE SERVER
postgres=# \des
List of foreign servers
Name | Owner | Foreign-data wrapper
-----------------+--------+----------------------
postgres_server | xxxxxx | postgres_fdw
(1 row)

Then let’s move on with a user mapping and a table to query.
postgres=# CREATE USER MAPPING FOR PUBLIC SERVER postgres_server OPTIONS (password '');
CREATE USER MAPPING
postgres=# CREATE TABLE aa AS SELECT 1 AS a, generate_series(1,3) AS b;
CREATE TABLE

As the foreign server used is the slave of our master, there is no need to create this table on the second node.

What remains is the creation of the foreign table.
postgres=# CREATE FOREIGN TABLE aa_foreign (a int, b int)
postgres=# SERVER postgres_server OPTIONS (table_name 'aa');
CREATE FOREIGN TABLE

Then if you query the foreign table.
postgres=# select * from aa_foreign;
a | b
---+---
1 | 1
1 | 2
1 | 3
(3 rows)

Yeah, done!

This feature still needs more testing, so go ahead and test it by yourself you might be surprised with the things you can do with it.

A foreign-data wrapper (FWD) in a Postgres server allows to fetch data from an foreign entity or a foreign server. In this case, the Postgres planner and executer have the notion of what is called a foreign scan, which can be called using customized routines and fetch data that is not directly stored inside the Postgres server itself.

The core code of Postgres includes one FDW which is fdw_file, postgres_fdw is planned to be also included at some point (9.3 discussions).

The installation of a FDW can be done since PostgreSQL 9.1 with the use of CREATE EXTENSION. There are many existing FDW modules that are developed and maintained by the community. Among some of them are:

  • oracle_fdw, to fetch data from an Oracle server
  • mysql_fdw, to fetch data from a MySQL server
  • pgsql_fdw (or sometimes postgres_fdw), to fetch data from another Postgres server
  • twitter_fdw, to fetch data from a Twitter server

Note: Once I thought about a git FDW as git is itself a NoSQL database managing concurrency of commits and branches its own way… But got no time to design or code it.

By the way, the FDW this post is focused on is called redis_fdw, which allows to fetch data from a foreign Redis server and materialize it directly on Postgres side. Before continuing reading this post, be sure that you already have running a Redis server and a Postgres server.
Here both Redis and Postgres server run on a local machine with respectively 6379 and 5432 as port numbers (default values).

Then it is time to install redis_fdw. First fetch the code.
mkdir $REDIS_SRC
cd $REDIS_SRC
git init
git remote add origin https://github.com/dpage/redis_fdw.git
git fetch origin
git checkout master

Then install it. Please note that the current version of the code is not compilable with Postgres 9.2 and upper versions, so for this post the Postgres server is 9.1.X.
make install USE_PGXS=1
This will add redis_fdw.so in folder lib of pgsql install folder and redis_fdw.control and redis_fdw–1.0.sql in share/extension.
Then finalize installation on the server by using CREATE EXTENSION.
postgres=# CREATE EXTENSION redis_fdw;
CREATE EXTENSION
postgres=# \dx redis_fdw
List of installed extensions
Name | Version | Schema | Description
-----------+---------+--------+--------------------------------------------------
redis_fdw | 1.0 | public | Foreign data wrapper for querying a Redis server
(1 row)

Then create the foreign server, its attached foreign table and a user mapping for remote connectivity (you can also refer to the redis_fdw README for additional details).
postgres=# CREATE SERVER redis_server
postgres-# FOREIGN DATA WRAPPER redis_fdw
postgres-# OPTIONS (address '127.0.0.1', port '6379');
CREATE SERVER
postgres=#
postgres=# CREATE FOREIGN TABLE redis_db0 (key text, value text)
postgres-# SERVER redis_server
postgres-# OPTIONS (database '0');
CREATE FOREIGN TABLE
postgres=# CREATE USER MAPPING FOR PUBLIC
postgres-# SERVER redis_server
postgres-# OPTIONS (password '');
CREATE USER MAPPING

On the Redis server side, let’s add a couple of keys with some values.
# redis-cli
redis 127.0.0.1:6379> set foo bar
OK
redis 127.0.0.1:6379> set foo2 bar2
OK

Finally it is possible to query the Redis data directly by connecting on Postgres.
postgres=# EXPLAIN VERBOSE SELECT * FROM redis_db0 WHERE key = 'foo2' OR key = 'foo';
QUERY PLAN
-----------------------------------------------------------------------------
Foreign Scan on public.redis_db0 (cost=10.00..12.00 rows=2 width=64)
Output: key, value
Filter: ((redis_db0.key = 'foo2'::text) OR (redis_db0.key = 'foo'::text))
Foreign Redis Database Size: 2
(4 rows)
postgres=# SELECT * FROM redis_db0 WHERE key = 'foo2' OR key = 'foo';
key | value
------+-------
foo | bar
foo2 | bar2
(2 rows)

And the set of key/values defined on Redis side have been fetched correctly.

Please note that redis_fdw code should not yet be used for production environment, I found for example that it crashes when the EXPLAIN query above is launched two times in a row. However, I think it is a good entry point to understand the possible Redis/Postgres interactions. It would also be worth stabilizing it and realigning it with Postgres master core code at some point.

This post presents some basics when using foreign data wrappers with PostgreSQL for external files.
FOREIGN DATA WRAPPER is a part of SQL/MED (Management of external data with SQL) and its implementation has begun since Postgres 8.4. This mechanism is based on COPY FROM to import data files directly into your database.
Those tests have been done with 9.2 (development version).

First be sure that the contrib module file_fdw is correctly installed for your server.
cd /to/postgres/folder/contrib/file_fdw
make install

At the time of this post, PostgreSQL tar just contains a fdw library for external files (file_fdw). Some complementary work for PostgreSQL fdw will be done as a development for 9.2.

If you do not install that, you may get the following error when trying to create an extension.
CREATE EXTENSION file_fdw;
ERROR: could not open extension control file "/to/install/folder/share/extension/file_fdw.control": cannot find the following file

Let’s then take a try.
First create a simple text file that will be converted. This file has a CVS format
michael@boheme:~ $ cat ~/data/test.data
1,5,a
2,4,b
3,3,c
4,2,d
5,1,e

Then time to create the extension necessary for the fdw.
template1=# CREATE EXTENSION file_fdw;
CREATE EXTENSION

Then you need to create a *server* that will pinpoint to your file on your server.
template1=# CREATE SERVER test_server FOREIGN DATA WRAPPER file_fdw;
CREATE SERVER

As a last step, you only need to create a table referred in a foreign server
template1=# CREATE FOREIGN TABLE testdata (
id1 int,
id2 int,
text1 char(1)
) SERVER test_server
OPTIONS ( filename '/home/michael/data/test.data', format 'csv' );
CREATE FOREIGN TABLE

Finally try to look at your data:
template1=# select * from testdata;
id1 | id2 | text1
-----+-----+-------
1 | 5 | a
2 | 4 | b
3 | 3 | c
4 | 2 | d
5 | 1 | e
(5 rows)

And you’re done, congrats!

©2010-2013 Michael Paquier All content is ©Copyright of Otacoo.com 2010-2013. Privacy Policy - Terms of Use