postgresql permission denied to foreign table pg_redis_fdw - postgresql

I am working with pg_rdeis_fdw from postgres.
When I try to insert a record to the existing schema from the postgres account, it all works fine.
However, when I try to do the same from another user, I get "permission denied for relation", though i gave the user the following privileges:
grant all on FOREIGN DATA WRAPPER redis_fdw to ami;
grant all on FOREIGN SERVER redis_server to ami;
grant all on ALL TABLES IN SCHEMA public to ami;
GRANT ALL PRIVILEGES ON TABLE user_redis_hash to ami;
The definition is as following (and as I was saying, works just fine from user postgres):
CREATE EXTENSION redis_fdw;
CREATE SERVER redis_server
FOREIGN DATA WRAPPER redis_fdw
OPTIONS (address '127.0.0.1', port '6379');
CREATE USER MAPPING FOR PUBLIC
SERVER redis_server
OPTIONS (password 'secret');
create foreign table user_redis_hash(key text, val text[])
server redis_server
options (database '0', tabletype 'hash', tablekeyset 'user:');
thanks,
Ami

In my case I had to change the owner of the foreign table to the right role. So you might try something like this (from the postgres account):
ALTER FOREIGN TABLE public.user_redis_hash OWNER TO ami;
If you have other foreign tables (as I did) and need to change them all, the following SQL will produce a series of SQL lines you can copy into psql prompt to update each foreign table.
SELECT 'ALTER FOREIGN TABLE '|| foreign_table_schema || '.' || foreign_table_name ||' OWNER TO ami;' FROM information_schema.foreign_tables WHERE NOT foreign_table_schema IN ('pg_catalog', 'information_schema') ORDER BY foreign_table_schema, foreign_table_name;
If you have other foreign tables for other servers or data wrappers that you do not want to change ownership on you can limit the above by adding AND foreign_server_name = 'redis_server' to the WHERE clause.

Related

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

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;

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.

postgres - how to test if peer of foreign table actually exists

I have two databases: let's call them primary (which holds actual data) and fdw (which contains foreign-data-wrapper of data in primary db).
I create simple table in primary db:
create schema myschema;
create table myschema.foo (id bigint, whatever text);
create table myschema.foov as select * from foo;
I create foreign table in fdw db accessing primary table through view:
create extension postgres_fdw;
create server remote_docker foreign data wrapper postgres_fdw options (host 'primary', dbname 'postgres', port '5432');
create schema remote_myschema;
create user mapping for current_user server remote_docker options (user 'postgres');
create foreign table remote_myschema.foo (id bigint, whatever text) server remote_docker options (schema_name 'myschema', table_name 'foov');
When executing select * from remote_myschema.foo query, everything works ok.
The problem: if I didn't create view in primary db, the create foreign table command in fdw db passes without error anyway. I am able to discover the nonexistency of view in primary db only at time of query execution on fdw db.
The question: is somehow possible to detect that foreign table is bound to nonexistent original? I compared pg_class data of foreign table in both cases and didn't find any difference nor anything in documentation. The only way I know at this moment is catching exception
do $$
declare
ex boolean;
begin
begin
execute 'select null from remote_myschema.foo';
ex := true;
exception when others then
ex := false;
end;
raise notice '%', ex::text;
end;
$$;
which is awful.
Thanks!
Catching the exception is the only way. Unless views are in the habit of suddenly disappearing at your site, you don't have to test it every time you use the foreign table. Testing once, right after you created it, is good enough.

Problems while Using postgres_fdw

I m getting some problem while using postgres_fdw.
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '192.162.0.1', port '5432', dbname 'Test');
CREATE USER MAPPING FOR postgres
SERVER foreign_server
OPTIONS (user 'foreign_user', password 'password');
CREATE FOREIGN TABLE foreign_table (
id serial NOT NULL,
data text)SERVER foreign_server
OPTIONS (schema_name 'public', table_name 'employee');
select * from employee where user ='foreign_user'
Now I can see entries are made to pg_foreign_data_wrapper, pg_foreign_server and pg_foreign_table tables.
But how do I access employee table of remote system.
I mean select * from employee where user ='foreign_user' doesn't give any result. Though it has data in Employee table of remote system.
Any idea please?
But How do I access employee table of remote system.
You just need to access the foreign table, say "SELECT * FROM foreign_table;".
The procedure seems fine, but your foreign table doesn't have a column named "user", so your query must cause an error.
It would be better to show what has happened actually. Showing actual query and error messages helps us understand where the problem is.

Why is postgres_fdw double-qualifying schemas?

Using postgres_fdw, I need to create the foreign tables in a specified schema to prevent name collisions. To isolate the issue I've been having, I set up two test postgres databases on the same cluster, import_test and export_test. Export_test has a table, foreign_schema.aa. On the server import_test, after doing the other FDW prerequisites, I ran:
CREATE FOREIGN TABLE local_schema.aa(
id serial NOT NULL,
dat text
) SERVER export_server OPTIONS (table_name 'foreign_schema.aa');
Then:
SELECT * FROM local_schema.aa;
When I do this, I get:
ERROR: relation "local_schema.foreign_schema.aa" does not exist
CONTEXT: Remote SQL command: SELECT id, dat FROM local_schema."foreign_schema.aa"
If I don't do any schema qualification, as in:
CREATE FOREIGN TABLE aa(
id serial NOT NULL,
dat text
) SERVER export_server OPTIONS (table_name 'aa');
And move the aa table to the public schema, the select works just fine.
If the command "SELECT id, dat FROM local_schema."foreign_schema.aa" is literally being run on the remote server, it's obvious why it doesn't work: local_schema."foreign_schema.aa" really doesn't exist on the remote server. For some reason, the postgres_fdw appears to be prepending the name given for table_name with the schema of the foreign table.
I need to specify the schema in the select query, because if I don't it doesn't see the foreign table. Achieving the schema qualification by preceding the select with setting the search path doesn't help either.
Is there anything I am doing wrong? If not, is there a workaround that will let me schema-qualify the foreign table?
EDIT: Per #Craig Ringer's suggestions, here's the self-contained psql input:
CREATE USER test_user SUPERUSER PASSWORD 'password';
SET ROLE test_user;
CREATE DATABASE import;
CREATE DATABASE export;
\c export test_user
CREATE SCHEMA export_schema;
CREATE TABLE export_schema.aa (
id serial PRIMARY KEY,
dat text
);
\c import test_user
CREATE EXTENSION postgres_fdw;
CREATE SERVER export_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', dbname 'export', port '5432');
CREATE USER MAPPING FOR test_user
SERVER export_server
OPTIONS (user 'test_user', password 'password');
CREATE SCHEMA import_schema;
CREATE FOREIGN TABLE import_schema.aa(
id serial NOT NULL,
dat text
) SERVER export_server OPTIONS (table_name 'export_schema.aa');
SELECT * FROM import_schema.aa;
Which yields this output:
ERROR: relation "import_schema.export_schema.aa" does not exist
CONTEXT: Remote SQL command: SELECT id, dat FROM import_schema."export_schema.aa"
Forgot to come back with resolution. Turns out sometime around the time I posted my bug report, the docs on postgres_fdw were updated. See the section "F.31.1.2. Object Name Options" and the schema_name option on this page: http://www.postgresql.org/docs/current/static/postgres-fdw.html.
I quote the mailing list reply:
"Use: OPTIONS (schema_name 'export_schema', table_name 'aa'); above.
Thanks,
Stephen"
So to resolve, just specify the foreign schema name in the schema_name option parameter.