How to set up permissions on foreign table using postgres_fdw? - postgresql

The source data is in a keys table in the public schema of database keys (reference pg docs: https://www.postgresql.org/docs/current/postgres-fdw.html) :
create table keys (
id varchar not null,
keyname varchar not null,
created timestamp default current_timestamp not null,
modified timestamp default current_timestamp not null
);
The referencing user/schema/database is vids/public/vids .
Set up the server connection
CREATE SERVER keys
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '1.2.3.4', port '5432', dbname 'keys');
Create the user mapping
CREATE USER MAPPING FOR vids
SERVER keys
OPTIONS (user 'keys', password 'keys');
Create the table mapping
create foreign table keys (
id varchar not null,
keyname varchar not null,
created timestamp default current_timestamp not null,
modified timestamp default current_timestamp not null
) server keys options (schema_name 'public', table_name 'keys');
Try to access the foreign table when connected as vids in the vids db:
vids=> select * from keys;
ERROR: permission denied for foreign table keys
I do not understand given that the user keys is the owner of the keys table in the foreign database. What should be done here?

From a comment by #jjanes:
the error message suggest the problem is on the local side". The local repfresentation of the foreign table is nowned by vids and vids does not have permissions to it. So it never gets far enough to figure out if keys has access to keys on the foreign side
So the correction to my steps was:
grant all on table keys to clips;

Related

postgresql, key is not present in table error, but key present in the table

I have tables providers, and provider_groups.
providers:
create table providers
(
id integer not null constraint providers_pkey primary key,
available boolean not null,
);
and provider_groups
create table provider_groups
(
id integer not null provider_groups_pkey primary key,
provider_id integer not null constraint fk_237d25c5d3e1ebb8
references providers on delete cascade,
type varchar(100) not null
);
create index idx_237d25c5d3e1ebb8
on provider_groups (provider_id);
and my application (which using of doctrine ORM) trying to update data for some provider and his related group. I'm sure both provider and group exists in database, but for some reason it's failing with error
SQLSTATE[23503]: Foreign key violation: 7 ERROR: insert or update on table "provider_groups" violates foreign key constraint "fk_237d25c5d3e1ebb8"\n
DETAIL: Key (provider_id)=(28007) is not present in table "providers".
but as I mentioned it's there, I can see it through database UI.
What I'm doing wrong??? Can it be related to some cache on DB side, as it's a pretty old logic running for a while and that error apears only now... Thanks in advice!

Postgresql [42P01] ERROR while creating foreign key

I want to create a foreign key in my postgresql db table but i'm receiving still message about non existing table (???!!?) It's driving me crazy because I have created necessary relation (address).
CREATE TABLE base_schema.station
(
id SERIAL PRIMARY KEY NOT NULL,
phone VARCHAR(20) NOT NULL,
station_address INT NOT NULL,
CONSTRAINT station_address_id_fk FOREIGN KEY (station_address)
REFERENCES address (id)
);
CREATE UNIQUE INDEX station_id_uindex ON base_schema.station (id);
I'm using jetbrains datagrip
Thanks in advance

Logging records in a postgresql database

I am having trouble thinking of a way to copy three fields out of a database into and append them to another table along with the current date. Basically what I want to do is:
DB-A: ID (N9), Name (C69), Phone (N15) {and a list of other fields I dont care about}
DB-B: Date (Todays date/time), Nane, Address, Phone (as above)
Would be great is this was a trigger in the DB on add or update of DB-A.
Greg
Quick and dirty using postgres_fdw
CREATE EXTENSION IF NOT EXISTS postgres_fdw ;
CREATE SERVER extern_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'foreignserver.co.uk', port '5432', dbname 'mydb');
CREATE USER MAPPING FOR myuser SERVER extern_server OPTIONS (user 'anotheruser');
-- Creating a foreign table based on table t1 at the server described above
CREATE FOREIGN TABLE foreign_t1 (
dba INT,
name VARCHAR(9),
phone VARCHAR(15)
)
SERVER extern_server OPTIONS (schema_name 'public', table_name 't1');
--Inserting data to a new table + date
INSERT INTO t2 SELECT dba,name,phone,CURRENT_DATE FROM foreign_t1;
-- Or just retrieving what you need placing the current date as a column
SELECT dba,name,phone,CURRENT_DATE FROM foreign_t1;

PostgreSQL audit table design with Multiple "User types"

I'm trying to implement an Audit table design in PostgreSQL, where I have different types of user id's that can be audited.
Let's say I have a table named admins (which belong to an organization), and table superadmins (which don't).
CREATE TABLE example.organizations (
id SERIAL UNIQUE,
company_name varchar(50) NOT NULL UNIQUE,
phone varchar(20) NOT NULL check (phone ~ '^[0-9]+$')
);
and an example of a potential admin design
CREATE TABLE example.admins (
id serial primary_key,
admin_type varchar not null,
#... shared data
check constraint admin_type in ("super_admins", "regular_admins")
);
CREATE TABLE example.regular_admins (
id integer primary key,
admin_type varchar not null default "regular_admins"
organization_id integer references example.organizations(id),
#... other regular admin fields
foreign key (id, admin_type) references example.admins (id, admin_type),
check constraint admin_type = "regular_admins"
);
CREATE TABLE example.super_admins (
id integer primary key,
admin_type varchar not null default "super_admins"
#... other super admin fields
foreign key (id, admin_type) references example.admins (id, admin_type),
check constraint admin_type = "super_admins"
);
Now an audit table
CREATE TABLE audit.organizations (
audit_timestamp timestamp not null default now(),
operation text,
admin_id integer primary key,
before jsonb,
after jsonb,
);
This calls for inheritance or polymorphism at some level, but I'm curious about how to design it. I've heard that using PostgreSQL's inheritance functionality is not always a great way to go, although I'm finding it to fit this use case.
I'll need to be able to reference a single admin id in the trigger that updates the audit table, and it would be nice to be able to get the admin information when selecting from the audit table without using multiple queries.
Would it be better to use PostgreSQL inheritance or are there other ideas I haven't considered?
I wouldn't say that it calls for inheritance or polymorphism. Admins and superadmins are both types of user, whose only difference is that the former belong to an organization. You can represent this with a single table and a nullable foreign key. No need to overcomplicate matters. Especially if you're using a serial as your primary key type: bad things happen if you confuse admin #2 for superadmin #2.

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.