Postgres 19 graph features

Postgres 19 adds graph features. This allow defining a graph representation of the existing relations. This does not change how data is stored, it’s more like view. This is pretty neat, because it helps to hide the way the data is linked together.

Let’s start with sample employee/department database schema and then add some test data there.

erDiagram
    EMPLOYEE {
        integer id PK
        varchar name UK
        varchar title
    }
    DEPARTMENT {
        integer id PK
        varchar name UK
    }
    EMPLOYMENT {
        integer id PK
        integer employee_id FK, UK
        integer department_id FK
    }
    REPORTING_LINE {
        integer id PK
        integer employee_id FK, UK
        integer manager_id FK
    }

    EMPLOYEE ||--o| EMPLOYMENT : has
    DEPARTMENT ||--o{ EMPLOYMENT : includes
    EMPLOYEE ||--o| REPORTING_LINE : reports
    EMPLOYEE ||--o{ REPORTING_LINE : manages
DROP PROPERTY GRAPH IF EXISTS organization_graph;
DROP TABLE IF EXISTS reporting_line, employment, employee, department;

CREATE TABLE department (
    id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name varchar(100) NOT NULL UNIQUE
);

CREATE TABLE employee (
    id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name varchar(100) NOT NULL UNIQUE,
    title varchar(100) NOT NULL
);

CREATE TABLE employment (
    id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    employee_id integer NOT NULL UNIQUE REFERENCES employee (id),
    department_id integer NOT NULL REFERENCES department (id)
);

CREATE TABLE reporting_line (
    id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    employee_id integer NOT NULL UNIQUE REFERENCES employee (id),
    manager_id integer NOT NULL REFERENCES employee (id),
    CHECK (employee_id <> manager_id)
);

Insert some test data

INSERT INTO department (name) VALUES
    ('Executive'),
    ('Engineering'),
    ('Product');

INSERT INTO employee (name, title) VALUES
    ('Ada Lovelace', 'CEO'),
    ('Grace Hopper', 'VP of Engineering'),
    ('Linus Torvalds', 'Engineering Manager'),
    ('Margaret Hamilton', 'Staff Engineer'),
    ('Edsger Dijkstra', 'Software Engineer'),
    ('Radia Perlman', 'Network Engineer'),
    ('Barbara Liskov', 'Product Director'),
    ('Alan Turing', 'Product Engineer');

INSERT INTO employment (employee_id, department_id)
SELECT employee.id, department.id
FROM (VALUES
    ('Ada Lovelace', 'Executive'),
    ('Grace Hopper', 'Executive'),
    ('Linus Torvalds', 'Engineering'),
    ('Margaret Hamilton', 'Engineering'),
    ('Edsger Dijkstra', 'Engineering'),
    ('Radia Perlman', 'Engineering'),
    ('Barbara Liskov', 'Product'),
    ('Alan Turing', 'Product')
) AS assignment(employee_name, department_name)
JOIN employee ON employee.name = assignment.employee_name
JOIN department ON department.name = assignment.department_name;

INSERT INTO reporting_line (employee_id, manager_id)
SELECT report.id, manager.id
FROM (VALUES
    ('Grace Hopper', 'Ada Lovelace'),
    ('Linus Torvalds', 'Grace Hopper'),
    ('Margaret Hamilton', 'Linus Torvalds'),
    ('Edsger Dijkstra', 'Linus Torvalds'),
    ('Radia Perlman', 'Linus Torvalds'),
    ('Barbara Liskov', 'Ada Lovelace'),
    ('Alan Turing', 'Barbara Liskov')
) AS hierarchy(employee_name, manager_name)
JOIN employee AS report ON report.name = hierarchy.employee_name
JOIN employee AS manager ON manager.name = hierarchy.manager_name;

Inserted data

Employee Title Department Manager
Ada Lovelace CEO Executive None
Grace Hopper VP of Engineering Executive Ada Lovelace
Linus Torvalds Engineering Manager Engineering Grace Hopper
Margaret Hamilton Staff Engineer Engineering Linus Torvalds
Edsger Dijkstra Software Engineer Engineering Linus Torvalds
Radia Perlman Network Engineer Engineering Linus Torvalds
Barbara Liskov Product Director Product Ada Lovelace
Alan Turing Product Engineer Product Barbara Liskov

Create the graph overlay on top of existing tables

CREATE PROPERTY GRAPH organization_graph
    VERTEX TABLES (
        employee LABEL employee PROPERTIES (name, title),
        department LABEL department PROPERTIES (name)
    )
    EDGE TABLES (
        reporting_line
            SOURCE KEY (employee_id) REFERENCES employee (id)
            DESTINATION KEY (manager_id) REFERENCES employee (id)
            LABEL reports_to NO PROPERTIES,
        employment
            SOURCE KEY (employee_id) REFERENCES employee (id)
            DESTINATION KEY (department_id) REFERENCES department (id)
            LABEL works_in NO PROPERTIES
    );
flowchart LR
    employee["employee vertex:<br> name, title"]
    department["department vertex:<br> name"]

    employee -->|reports_to| employee
    employee -->|works_in| department

Traditional query with joins

SELECT
    report.name AS employee,
    report.title,
    manager.name AS manager,
    manager_department.name AS manager_department
FROM employee AS report
JOIN reporting_line
    ON reporting_line.employee_id = report.id
JOIN employee AS manager
    ON manager.id = reporting_line.manager_id
JOIN employment AS manager_employment
    ON manager_employment.employee_id = manager.id
JOIN department AS manager_department
    ON manager_department.id = manager_employment.department_id
WHERE manager_department.name = 'Engineering'
ORDER BY report.name;
Employee Title Manager Manager department
Edsger Dijkstra Software Engineer Linus Torvalds Engineering
Margaret Hamilton Staff Engineer Linus Torvalds Engineering
Radia Perlman Network Engineer Linus Torvalds Engineering

Then same query using graph

(employee) -[reports_to]-> (manager) -[works_in]-> (Engineering)
SELECT employee, title, manager, manager_department
FROM GRAPH_TABLE (
    organization_graph
    MATCH
        (report IS employee)
        -[IS reports_to]->
        (manager IS employee)
        -[IS works_in]->
        (department IS department WHERE department.name = 'Engineering')
    COLUMNS (
        report.name AS employee,
        report.title AS title,
        manager.name AS manager,
        department.name AS manager_department
    )
)
ORDER BY employee;
Employee Title Manager Manager department
Edsger Dijkstra Software Engineer Linus Torvalds Engineering
Margaret Hamilton Staff Engineer Linus Torvalds Engineering
Radia Perlman Network Engineer Linus Torvalds Engineering