As a complement to and mainly for a detailed response to .
The theoretical part is well described in the documentation — . Below, a practical implementation of a small specific business task — hiding deleted data. A study dedicated to the implementation of is presented separately.

The article contains nothing new, no hidden meanings or secret knowledge. It is simply a sketch about the practical implementation of a theoretical idea. If anyone is interested — read on. If not, don’t waste your time.
Task Definition
Without delving deeply into the subject area, briefly, the task can be formulated as follows: there is a table implementing a certain business entity. Rows in the table can be deleted, but they cannot be physically removed, they must be hidden.
For it is said — "Do not delete anything, only rename it. The internet stores EVERYTHING"
Along the way, it is preferable not to rewrite the existing stored functions that work with this entity.
To implement this concept, the table has an attribute is_deleted. Next, it's simple — you need to ensure that the client can see only the rows where the attribute is_deleted is false. This is where the mechanism of Row Level Security is used.
Implementation
We create a separate role and schema
CREATE ROLE repos;
CREATE SCHEMA repos;We create the target table
CREATE TABLE repos.file
(
...
is_del BOOLEAN DEFAULT FALSE
);
CREATE SCHEMA reposWe enable Row Level Security
ALTER TABLE repos.file ENABLE ROW LEVEL SECURITY;
CREATE POLICY file_invisible_deleted ON repos.file FOR ALL TO dba_role USING (NOT is_deleted);
GRANT ALL ON TABLE repos.file to dba_role;
GRANT USAGE ON SCHEMA repos TO dba_role;Service function — deleting a row in the table
CREATE OR REPLACE repos.delete(curr_id repos.file.id%TYPE)
RETURNS integer AS $$
BEGIN
...
UPDATE repos.file
SET is_del = TRUE
WHERE id = curr_id;
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;Business function — deleting a document
CREATE OR REPLACE business_functions.deleteDoc(doc_for_delete JSON)
RETURNS JSON AS $$
BEGIN
...
PERFORM repos.delete(doc_id);
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;Results
The client deletes the document
SELECT business_functions.delCFile((SELECT json_build_object('CId', 3)));After deletion, the client cannot see the document
SELECT business_functions.getCFile((SELECT json_build_object('CId', 3)));
-----------------
(0 rows)But the document is not deleted in the database, only the attribute is_del
psql -d my_db
SELECT id, name, is_del FROM repos.file;
id | name | is_del
--+---------+------------
1 | test_1 | t
(1 row)Which is exactly what was required in the task.
Summary
If the topic is of interest, the next study can demonstrate an example of implementing a role-based access model using Row Level Security.
Source: habr.com
