How to create an (FDW) foreign table and map it to a different schema? - postgresql

This is how I defined the foreign table:
CREATE FOREIGN TABLE ftbl_employee (
id UUID,
name VARCHAR,
)
SERVER company_registry_dbserver
OPTIONS (schema_name 'company', table_name 'company_employee');
It created the foreign table successfully. However, when I list the foreign table, It has defaulted to public schema. See foreign_table_schema column:
> select * from information_schema.foreign_tables;
foreign_table_catalog
foreign_table_schema
foreign_table_name
foreign_server_catalog
foreign_server_name
sandbox
public
ftbl_employee
sandbox
company_registry_dbserver
I would like to map it into the company schema in our sandbox database server instead of the public schema.

The column information_schema.foreign_tables holds the schema where the foreign table is stored locally, not the schema of the table in the target database. So, there is no way you can create this foreign table in the schema company if it does not exist locally! You need to either locally run ..
CREATE SCHEMA company;
.. or live with the foreign table in the public schema. Keep in mind that a foreign table is nothing more than a "gateway" to a table that resides in a different database / server. If you wanna know more details on the foreign table, e.g. name or schema, check the view pg_foreign_table:
SELECT relname, ftoptions
FROM pg_foreign_table
JOIN pg_class ON ftrelid = oid;

Related

Foreign Table that references ALL columns of the origin table

Is it possible to create a foreign table that lists all columns of the original table, like this somehow?
CREATE FOREIGN TABLE localschema.localtable (/* list all columns of foreign_table here */)
SERVER foreignserver
OPTIONS (schema_name 'foreign_schema', table_name 'foreign_table');
Use IMPORT FOREIGN SCHEMA:
IMPORT FOREIGN SCHEMA foreign_schema LIMIT TO (foreign_table)
FROM SERVER foreignserver INTO localschema;
If you need the foreign table name to be different, rename it.

Pre-fix the foreign table with the schema - postgres_pwd

If I follow: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#postgresql-commondbatasks-fdw, how can I pre-fix the tables with the schema I am retrieving tables from, e.g.
IMPORT FOREIGN SCHEMA lands
LIMIT TO (land, land2)
FROM SERVER foreign_server INTO public;
The created tables are named land and land2. Is it possible to prefix land and land2 with 'lands', e.g. 'lands_land' and 'lands_land2'?
With psql and recent PostgreSQL versions, you could simply run (after the IMPORT FOREIGN SCHEMA):
SELECT format(
'ALTER FOREIGN TABLE public.%I RENAME TO %I;',
relname,
'lands_' || relname
)
FROM pg_class
WHERE relkind = 'f' -- foreign table
AND relnamespace = 'public'::regnamespace \gexec
The \gexec will interpret each result row as an SQL stateent and execute it.
Another option that I'd like better is to keep the original names, but use a different schema for the foreign tables:
IMPORT FOREIGN SCHEMA lands
LIMIT TO (land, land2)
FROM SERVER foreign_server INTO lands;
Then all foreign tables will be in a schema lands, and you have the same effect in a more natural fashion. You can adjust search_path to include the lands schema.

updating table with Postgresql Foreign data wrapper

I created a foreign data wrapper table named t_user into mySchema.
IMPORT FOREIGN SCHEMA public LIMIT TO (t_user)
FROM SERVER myServer INTO mySchema;
The myServer side t_user added some column, but the foreign table didn't update accordingly.
I tried to delete the foreign table t_user, but it was used by my view and materialized view t_user, so the deletion failed.
Any ideas on how to update this table?
As you have seen, the foreign table definition does not change when the underlying table changes.
If all you did is add a column, you can use ALTER FOREIGN TABLE to add a corresponding column to the foreign table. That should work even if views depend on the foreign table.
For example, if the column is of type text, you can do:
ALTER FOREIGN TABLE t_user ADD COLUMN my_column text;

“Error 42P01: relation does not exist” (non public schema in PostgreSQL)

I want to create a foreign key but I got Error 42P01: relation solicitantes does not exist.
I have to schemas: public and laboratorio.
My table is called procedencias. I want to create a foreign key to solicitantes table. Both belongs to laboratorio schema. Even the autocomplete of the target table field works and find the table.
I see that:
I can create the foreing key to any tables of the public schema.
I can't create the foreing key to any tables of the laboratorio schema.
Error when creating a foreign key.
I am using Jetbrains DataGrip software.
This is the DDL of the table called "solicitantes":
CREATE TABLE laboratorio.solicitantes
(
id_solicitante serial NOT NULL,
nombre_solicitante character varying(100) NOT NULL,
CONSTRAINT solicitantes_pkey PRIMARY KEY (id_solicitante)
)
WITH (
OIDS=FALSE
);
ALTER TABLE laboratorio.solicitantes
OWNER TO roby;
CREATE UNIQUE INDEX solicitantes_id_solicitante_uindex
ON laboratorio.solicitantes
USING btree
(id_solicitante);
CREATE UNIQUE INDEX solicitantes_nombre_solicitante_uindex
ON laboratorio.solicitantes
USING btree
(nombre_solicitante COLLATE pg_catalog."default");
I think I have to specify the schema name but I don't know where to do it in DataGrip.
I had the same issue with adding foreign keys to a table in a custom schema from the modify table window. Adding schema to the "Target table" field did not work either. Instead I selected "Open in editor" rather than "Execute in database" and added the schema to the table name in the generated statement and it ran fine.
have you tried to add the explicit schema to the table solicitantes?

Cannot create foreign key constraint on table w/ inheritance

I'm trying to add a foreign key constraint to an existing table:
ALTER TABLE address
ADD FOREIGN KEY(company_id)
REFERENCES company(company_id) ON DELETE CASCADE DEFERRABLE;
That fails with:
ERROR: insert or update on table "address" violates \
foreign key constraint "address_company_id_fkey"
DETAIL: Key (company_id)=(83376) is not present in table "company".
Yet the company table does have that key:
DB=> SELECT company_id FROM company WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I suspect that this is due to table inheritance (old database, very historic reasons), company is a base table and one derived table is the person table. Which is the one containing the actual key:
DB=> SELECT company_id FROM person WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I'm specifically targeting the base table (assuming it contains the data of all derived tables) because the address rows refer to different derived tables.
Is there a way to make that work?
Or as an alternative, kinda even better, is there a way to have foreign keys targeting specific derived tables?