Postgres, how to set up queries between different databases

In our System, data about users is recorded in one database, and data about their trades in another; without additional settings, Postgres does not allow using data from different databases in one request.

That is, a request like:

select a.id from auth.public.user a join trade.public.tenders t on a.id = t.user_id;

Will cause the error “[0A000] ERROR: cross-database references are not implemented”.

What to do ?

You need to create a wrapper for an external table; read below on how to do this.

Setting up an external database

We connect to the DBMS under the super user postgres, connect to the database, which is external to the database from which we will make the request.

docker exec -it postgres psql -U postgres
\c trade

We create the data source we need, in our case this is a view

create or replace view tender_users AS
select    t.id_user
from    tender t        
group by    id_user
order by id_user
;

We give rights to the created source (yes, rights to absolutely everything, for now we can do that)

GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA public TO trade;

In addition, this is an illogical command, because it is needed even if we create views under the trade user, but without it it does not work, it gives an error of not having enough rights (when we make a request through FOREIGN DATA WRAPPER).

Setting up your own database

Switch to the database from which we will make queries

\c prod

We connect the extension for queries to an external database

create extension postgres_fdw;

Checking that the extension is enabled

\dx

Must see:

                               List of installed extensions
     Name     | Version |   Schema   |                    Description
--------------+---------+------------+----------------------------------------------------
 plpgsql      | 1.0     | pg_catalog | PL/pgSQL procedural language
 postgres_fdw | 1.0     | public     | foreign-data wrapper for remote PostgreSQL servers
(2 rows)

We need the second line, the first one is “stray”.

Creating an external server

CREATE SERVER tenders FOREIGN DATA WRAPPER postgres_fdw  OPTIONS (dbname 'trade', host 'postgres', port '5432');

We issue rights to use the extension and server

GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw to prod;
GRANT USAGE ON FOREIGN SERVER tenders TO prod;

Now the most important thing is to set the credentials for connecting to the external database

CREATE USER MAPPING for prod SERVER tenders OPTIONS (user 'trade', password '***');

Connecting the data source

Now you can create external tables manually, or automatically. You can read how to create a data source manually using the links from the bibliography at the end of the article. If automatically, then:

IMPORT FOREIGN SCHEMA public LIMIT TO (tender_users) FROM SERVER tenders INTO public;

Checking that the data is readable

prod=# select count(*) from tender_users;
 count
-------
     0
(1 row)

There are no reading errors, which means the connection has been successfully established. Now we can use the data from the external table in queries against our internal tables.

Success!

Postscriptum

The last time I did this was 5 years ago, and perhaps my knowledge is outdated, how is this problem solved in current versions of Postgres? write in the comments.

DBMS version

prod=# select version();
                                                    version
---------------------------------------------------------------------------------------------------------------
 PostgreSQL 13.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
(1 row)

References

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *