-
Notifications
You must be signed in to change notification settings - Fork 651
CartoDB onpremise FDW
This guide shows how data from an external database can be rendered using the Maps API. SQLite is used in the example to simplify setup, but any database (or datasource) that is supported by an FDW for PostgreSQL could be used instead.
In order to access the on-premise PostgreSQL you need to login in the internal CartoDB container. First login in the VM:
ssh ubuntu@onpremise_ip
# pass: ubuntu
Then, login in the container:
cartodb-ctl -c
In a production situation, the remote database would already be running on a server somewhere in the customer's network. For this example, we will create a new SQLite database.
# sqlite3 /tmp/test.db
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> CREATE TABLE test (a int);
sqlite> insert into test values (10);
sqlite> insert into test values (10);
sqlite> insert into test values (10);
First you need to figure out what internal CartoDB database name has been assigned to your CartoDB user name. In order to know the database name you can do:
# psql \
-U postgres \
-d cartodb_production \
-c "select database_name from users where username = 'YOURUSERNAME'";
database_name
----------------------------------------------------------
cartodb_dev_user_b7861beb-21d4-46bc-ae00-5f09f77701a6_db
Then connect to the database:
# psql -U postgres cartodb_dev_user_b7861beb-21d4-46bc-ae00-5f09f77701a6_db
Now add FDW extension (this changes if you are not using sqlite) and create the FDW table. Each FDW documents the way the external table can be created
CREATE EXTENSION sqlite_fdw;
CREATE SERVER sqlite_server
FOREIGN DATA WRAPPER sqlite_fdw
OPTIONS (database '/tmp/test.db');
CREATE FOREIGN TABLE local_table
(a int)
SERVER sqlite_server
OPTIONS (table 'test');
Then test that it works:
SELECT * FROM local_table;
In order to provide public access to an FDW table, you need to ensure that the publicuser
has been granted the SELECT
privilege to the foreign tables:
GRANT SELECT ON local_table TO publicuser;
GRANT ALL ON local_table TO development_cartodb_user_b7861beb-21d4-46bc-ae00-5f09f77701a6;
Now you can use that table in any CartoDB Map by including it in a SQL query.
The main problem you will find is that after you update your data in your remote database the tiles are not updated. This is because the CartoDB cache system uses table names and a special trigger to know when a table is updated to invalidate caches but in case of remote tables this is not possible. We can work around this in two ways:
- Manually invoke cache invalidation, using
CDB_TableMetadataTouch('local_table')
every time we need to invalidate cache for that table. - Avoid the cache altogether, by adding a function that hides the tables you are using. When CartoDB does not know what tables are being used, cache headers are not set so the maps API always hits the database.
See also, https://github.com/CartoDB/Windshaft-cartodb/pull/297
The postgres_fdw
extension in included with the PostgreSQL source code. Enter the contrib
directory, make
and make install
and it is ready to go. Note the use of options to control what remote table the foreign table is mapped to, what columns are mapped to, and whether a foreign table is writeable or not.
CREATE EXTENSION postgres_fdw;
CREATE SERVER film_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (
host 'localhost',
dbname 'foodb',
port '5432',
use_remote_estimate 'false',
updatable 'true'
);
CREATE USER MAPPING
FOR bob
SERVER film_server
OPTIONS (
user 'bob',
password 'secret'
);
CREATE FOREIGN TABLE films (
code char(5) NOT NULL,
title varchar(40) OPTIONS ( column_name 'title_en' ) NOT NULL,
did integer NOT NULL,
date_prod date,
kind varchar(10),
len interval hour to minute
)
SERVER film_server
OPTIONS (
table_name 'films_en',
schema_name 'webapps',
use_postgis 'true', -- See below
updatable 'false'
);
We have created a patched version of PostgreSQL that includes a postgres_fdw
with support for PostGIS functions and operators. This version will pass spatial restrictions and functions to the remote database, making efficient mapping of remote spatial tables a possibility.
- https://github.com/pramsey/postgres/tree/9.3-postgres-fdw-postgis
- https://github.com/pramsey/postgres/tree/9.4-postgres-fdw-postgis
Retrieve and build the appropriate branch for the version of PostgreSQL you want. Everything is exactly the same except there is an additional table option.
-
use_postgis
: When enabled on a foreign table will pass down any PostGIS operators or functions it receives for execution on the remote server. Naturally the remote server must have PostGIS enabled or this won't work at all.
See CartoDB Oracle FDW.