Row level security - Update Rows - postgresql

Hi I am working with Postgres, I have one role "my_role", and I want to update records from one table only where my corporate_id is related to other table.
I want to create a Policy to person table, and I have a corporate_id from my corporate table to drive to get this information would be something like these:
SELECT * FROM person p
INNER JOIN person_brand a ON p.person_id=a.person_id
INNER JOIN brand b ON a.brand_id=b.brand_id
INNER JOIN corporate c on b.corporate_id=c.corporate_id
WHERE c.corporate_id=corporate_id
I my policy will be something like these:
ALTER TABLE core.person ENABLE ROW LEVEL SECURITY;
CREATE POLICY person_corporation_all
ON person
AS PERMISSIVE
FOR UPDATE
TO "my_role"
USING (EXISTS(SELECT 1 FROM person p
INNER JOIN person_brand a ON p.person_id=a.person_id
INNER JOIN brand b ON a.brand_id=b.brand_id
INNER JOIN corporate c on b.corporate_id=c.corporate_id
WHERE c.corporate_id=corporate_id));
But show me this error:
ERROR: column reference "corporate_id" is ambiguous
SQL state: 42702
What I need to send as variable into my query?
Regards

You will have a nested policy because inside the verification you have the person table again, you will need to remove it, and refers to the columns using the name of the table person, for example:
CREATE POLICY person_corporation_all
ON person
AS PERMISSIVE
FOR UPDATE
TO "my_role"
USING (EXISTS(SELECT 1 FROM person_brand a
INNER JOIN brand b ON a.brand_id=b.brand_id
INNER JOIN corporate c on b.corporate_id=c.corporate_id
WHERE a.person_id=person.person_id and c.corporate_id=person.corporate_id));

Related

N-Way table joins in ksqlDB

I have three ksqldb tables, whose relation is illustrated in the picture below. I must join them.
This query will result in an error:
CREATE TABLE `reviewer-email-user`
AS SELECT *
FROM USER
INNER JOIN REVIEWER ON USER.USERID = REVIEWER.USERID
INNER JOIN EMAILADDRESS ON USER.USERID = EMAILADDRESS.USERID
EMIT CHANGES;
And the error is:
Could not determine output schema for query due to error: Invalid join condition: table-table joins require to join on the primary key of the right input table. Got USER.USERID = REVIEWER.USERID
So, how do I join these three ksqldb tables? Thank you.
table-table joins expect the join condition to have the primary key on the right side and therefore, the following will not work:
ksql> CREATE TABLE reviewer_user
> AS SELECT *
> FROM REVIEWER
> INNER JOIN USER ON USER.user_id = REVIEWER.user_id
>EMIT CHANGES;
Could not determine output schema for query due to error: Cannot add table 'REVIEWER_USER': A table with the same name already exists
Statement: CREATE TABLE REVIEWER_USER WITH (KAFKA_TOPIC='REVIEWER_USER', PARTITIONS=2, REPLICAS=1) AS SELECT *
FROM REVIEWER REVIEWER
INNER JOIN USER USER ON ((USER.USER_ID = REVIEWER.USER_ID))
EMIT CHANGES;
however the following query does work (note that I have flipped the left and right side of the join)
ksql> CREATE TABLE reviewer_user
> AS SELECT *
> FROM REVIEWER
> INNER JOIN USER ON REVIEWER.user_id = USER.user_id
>EMIT CHANGES;
Message
---------------------------------------------
Created query with ID CTAS_REVIEWER_USER_11
---------------------------------------------
Another limitation of table-table joins is that it doesn't support n-way joins, so you would have to create 2 new tables(reviewer_user and email_user) by performing joins as suggested above and then finally perform a join on them to get your final result.

Postgres - How to join on two columns?

I have a table containing account information:
And another table, containing transactions information:
I'd like to retrieve both the titles from transactions.from_acc_id and transactions.to_acc_id
So far, I'm only able to retrieve either one or the other with the following JOIN:
SELECT transactions.transaction_type,
transactions.from_acc_id,
transactions.to_acc_id,
transactions.amount,
account.title AS "ACCOUNT DESTINATION"
FROM transactions
JOIN account
ON transactions.to_acc_id = account.acc_id
This gives me the title of transactions.to_acc_id.
How can I add another field containing the title of transactions.from_acc_id with the same SELECT statement, please ?
Thanks
EDIT: I'd like to keep all field from the Select statement, adding the title of transactions.from_acc_id where is pertinent
You join your account table in twice and give each instance its own alias. Furthermore, to ensure that every record from transactions table shows up and only those records from your accounts table (both source and destination), use a LEFT OUTER JOIN instead of your implicit INNER JOIN that you are currently using.
SELECT transactions.transaction_type,
transactions.from_acc_id,
transactions.to_acc_id,
transactions.amount,
dest.title AS "ACCOUNT DESTINATION",
src.title AS "ACCOUNT SOURCE"
FROM transactions
LEFT OUTER JOIN account as dest
ON transactions.to_acc_id = dext.acc_id
LEFT OUTER JOIN account as src
ON transactions.from_acc_id = src.acc_id
For more information on types of joins that are available in most databases, check out W3Schools SQL Joins page
Simply join the table twice. Use table aliases to tell the source account from the target account.
SELECT
t.transaction_type,
t.from_acc_id,
t.to_acc_id,
t.amount,
from_acc.title AS from_account,
to_acc.title AS to_account
FROM transactions t
LEFT JOIN account from_acc ON from_acc.acc_id = t.from_acc_id
LEFT JOIN account to_acc ON to_acc.acc_id = t.to_acc_id

HQL update column with COUNT

I'm working with Hibernate thus HQL, linked to a PostgreSQL database.
I have a table users and a table teams that are linked with a ManyToMany condition throught the table teams_users.
I'd like to update or select the table team so the property usersCount takes the amount of users belonging to a team.
I do not want to add a #Formula to my Entity Class, because I don't want it to be executed all the time, that's too wastful on big JOIN FETCH query where I do not need the count.
I other words, I'd like to find the HQL equivalent of the following PSQL query
UPDATE teams t
SET users_count = (SELECT COUNT(ut.*)
FROM teams t1
LEFT JOIN teams_users tu
ON t1.id = tu.team_id
WHERE t1.id = t.id
GROUP BY t1.id);
OR
An equivalent of the following
SELECT t.*, count(tu.*) AS users_count
FROM teams t
LEFT JOIN teams_users tu
ON t.id = tu.team_id
GROUP BY t.id;
Unsuccessful tries (to get an idea)
UPDATE Team t SET
t.usersCount = COUNT(t.users)
UPDATE Team t SET
t.usersCount = (SELECT COUNT(t1.users) FROM Team t1 WHERE t1.id = t.id)
SELECT t, count(t.users) AS t.usersCount
FROM Team t
I've found the solution for the UPDATE query.
It simply is
UPDATE Team t
SET t.usersCount = (SELECT COUNT(u) from t.users u)
It makes an extra join on the table users whilst the table teams_users would be enought but well... It works.
If anyone has ths solution for the SELECT one, I'm still curious !

SQL Tables with no direct relation

I have a PostgreSQL DB and I need to build a query to retrieve the information from a table that has no direct link with the main one.
The client is linked to the client_identity_document through its UUID and client_identity_document to the identity_document through the uuid_identity_document. I know I have to make an inner join, but I just started with relational databases and I don't know exactly the syntax to join tables that don't have direct relation.
try this
select *
from client c
inner join client_identity_document cid on c.UUID = cid.UUID_Client
inner join identity_document id on cid.uuid_identity_document = id.UUID

Can't disable order joins in Postgresql

Postgresql provides a parameter join_collapse_limit = 1 to disable order of joins. But when I set the parameter and reset the server, the query plan is not changed and there still is order join optimization. My query FROM table is like this
FROM
student as group_A,
student as group_B,
student as group_C
WHERE ...
If users want to use join_collapse_limit = 1 to disable join reordering, explicit JOINS must be provided in the query. For example, the above FROM table should be
FROM
student as group_A CROSS JOIN
student as group_B CROSS JOIN
student as group_C
WHERE ...