Add missing ERD/SQL tabs and fix some requests
@@ -8,6 +8,8 @@ You can go download erd from https://github.com/BurntSushi/erd/releases and then
|
|||||||
./erd_static-x86-64 -i diagrams/film.er -o docs/_static/film.png
|
./erd_static-x86-64 -i diagrams/film.er -o docs/_static/film.png
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The fonts used belong to the GNU FreeFont family. You can download them here: http://ftp.gnu.org/gnu/freefont/
|
||||||
|
|
||||||
## LaTeX
|
## LaTeX
|
||||||
|
|
||||||
The schema structure diagram is done with LaTeX. You can use a GUI like https://www.mathcha.io/editor to create the .tex file.
|
The schema structure diagram is done with LaTeX. You can use a GUI like https://www.mathcha.io/editor to create the .tex file.
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
|
[Box_Office]
|
||||||
|
*bo_date
|
||||||
|
*+film_id
|
||||||
|
gross_revenue
|
||||||
|
|
||||||
|
[Films]
|
||||||
|
*id
|
||||||
|
+director_id
|
||||||
|
title
|
||||||
|
`...`
|
||||||
|
|
||||||
|
Box_Office +--1 Films
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
# Build using: -e ortho
|
||||||
|
|
||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
[Employees]
|
[Employees]
|
||||||
*id
|
*id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeSerif"}
|
||||||
|
|
||||||
[Films]
|
[Films]
|
||||||
*id
|
*id
|
||||||
+director_id
|
+director_id
|
||||||
@@ -31,6 +34,12 @@ year
|
|||||||
*+film_id
|
*+film_id
|
||||||
rank
|
rank
|
||||||
|
|
||||||
|
[Technical_Specs]
|
||||||
|
*+film_id
|
||||||
|
runtime
|
||||||
|
camera
|
||||||
|
sound
|
||||||
|
|
||||||
Roles *--1 Actors
|
Roles *--1 Actors
|
||||||
Roles *--1 Films
|
Roles *--1 Films
|
||||||
|
|
||||||
@@ -38,3 +47,5 @@ Nominations *--1 Competitions
|
|||||||
Nominations *--1 Films
|
Nominations *--1 Films
|
||||||
|
|
||||||
Films *--1 Directors
|
Films *--1 Directors
|
||||||
|
|
||||||
|
Films 1--1 Technical_Specs
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
# Build using: -e ortho
|
||||||
|
|
||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
[Addresses]
|
[Addresses]
|
||||||
*id
|
*id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
|
[Premieres]
|
||||||
|
*id
|
||||||
|
location
|
||||||
|
date
|
||||||
|
+film_id
|
||||||
|
|
||||||
|
[Films]
|
||||||
|
*id
|
||||||
|
+director_id
|
||||||
|
title
|
||||||
|
`...`
|
||||||
|
|
||||||
|
Premieres *--1 Films
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
# Build using: -e ortho
|
||||||
|
|
||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
[Presidents]
|
[Presidents]
|
||||||
*id
|
*id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
# Build using: -e ortho
|
||||||
|
|
||||||
|
entity {font: "FreeSans"}
|
||||||
|
relationship {font: "FreeMono"}
|
||||||
|
|
||||||
[Users]
|
[Users]
|
||||||
*id
|
*id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
@@ -24,7 +24,56 @@ Relationships
|
|||||||
|
|
||||||
For example, consider a database of films and their awards:
|
For example, consider a database of films and their awards:
|
||||||
|
|
||||||
.. image:: ../../_static/film.png
|
.. _erd_film:
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. group-tab:: ERD
|
||||||
|
|
||||||
|
.. image:: ../../_static/film.png
|
||||||
|
|
||||||
|
.. code-tab:: postgresql SQL
|
||||||
|
|
||||||
|
create table actors(
|
||||||
|
id int primary key generated always as identity,
|
||||||
|
first_name text,
|
||||||
|
last_name text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table directors(
|
||||||
|
id int primary key generated always as identity,
|
||||||
|
first_name text,
|
||||||
|
last_name text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table films(
|
||||||
|
id int primary key generated always as identity,
|
||||||
|
director_id int references directors(id),
|
||||||
|
title text,
|
||||||
|
year int,
|
||||||
|
rating numeric(3,1),
|
||||||
|
language text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table roles(
|
||||||
|
film_id int references films(id),
|
||||||
|
actor_id int references actors(id),
|
||||||
|
character text,
|
||||||
|
primary key(film_id, actor_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table competitions(
|
||||||
|
id int primary key generated always as identity,
|
||||||
|
name text,
|
||||||
|
year int
|
||||||
|
);
|
||||||
|
|
||||||
|
create table nominations(
|
||||||
|
competition_id int references competitions(id),
|
||||||
|
film_id int references films(id),
|
||||||
|
rank int,
|
||||||
|
primary key (competition_id, film_id)
|
||||||
|
);
|
||||||
|
|
||||||
.. _many-to-one:
|
.. _many-to-one:
|
||||||
|
|
||||||
@@ -136,24 +185,7 @@ Many-to-many relationships
|
|||||||
|
|
||||||
The join table determines many-to-many relationships. It must contain foreign keys to other two tables and they must be part of its composite key.
|
The join table determines many-to-many relationships. It must contain foreign keys to other two tables and they must be part of its composite key.
|
||||||
|
|
||||||
For the many-to-many relationship between ``films`` and ``actors``, the join table ``roles`` is:
|
Thus, it can detect the join table ``roles`` between ``films`` and ``actors``:
|
||||||
|
|
||||||
.. code-block:: postgresql
|
|
||||||
|
|
||||||
create table roles(
|
|
||||||
film_id int references films(id)
|
|
||||||
, actor_id int references actors(id)
|
|
||||||
, primary key(film_id, actor_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- the join table can also be detected if the composite key has additional columns
|
|
||||||
|
|
||||||
create table roles(
|
|
||||||
id int generated always as identity,
|
|
||||||
, film_id int references films(id)
|
|
||||||
, actor_id int references actors(id)
|
|
||||||
, primary key(id, film_id, actor_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
|
|
||||||
@@ -177,6 +209,18 @@ For the many-to-many relationship between ``films`` and ``actors``, the join tab
|
|||||||
".."
|
".."
|
||||||
]
|
]
|
||||||
|
|
||||||
|
The join table can also be detected if the composite key has additional columns:
|
||||||
|
|
||||||
|
.. code-block:: postgresql
|
||||||
|
|
||||||
|
create table roles(
|
||||||
|
id int generated always as identity,
|
||||||
|
, film_id int references films(id)
|
||||||
|
, actor_id int references actors(id)
|
||||||
|
, character text,
|
||||||
|
, primary key(id, film_id, actor_id)
|
||||||
|
);
|
||||||
|
|
||||||
.. _one-to-one:
|
.. _one-to-one:
|
||||||
|
|
||||||
One-to-one relationships
|
One-to-one relationships
|
||||||
@@ -184,38 +228,27 @@ One-to-one relationships
|
|||||||
|
|
||||||
One-to-one relationships are detected in two ways.
|
One-to-one relationships are detected in two ways.
|
||||||
|
|
||||||
|
- When the foreign key is a primary key as specified in the :ref:`DB structure example <erd_film>`.
|
||||||
- When the foreign key has a unique constraint.
|
- When the foreign key has a unique constraint.
|
||||||
|
|
||||||
.. code-block:: postgresql
|
.. code-block:: postgresql
|
||||||
|
|
||||||
CREATE TABLE technical_specs(
|
CREATE TABLE technical_specs(
|
||||||
film_id INT REFERENCES films UNIQUE,
|
film_id INT REFERENCES films UNIQUE,
|
||||||
runtime TIME,
|
runtime TIME,
|
||||||
camera TEXT,
|
camera TEXT,
|
||||||
sound TEXT
|
sound TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
- When the foreign key is a primary key.
|
|
||||||
|
|
||||||
.. code-block:: postgresql
|
|
||||||
|
|
||||||
-- references Films using the primary key as a foreign key
|
|
||||||
CREATE TABLE technical_specs(
|
|
||||||
film_id INT PRIMARY KEY REFERENCES films,
|
|
||||||
runtime TIME,
|
|
||||||
camera TEXT,
|
|
||||||
sound TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
|
|
||||||
.. code-tab:: http
|
.. code-tab:: http
|
||||||
|
|
||||||
GET /films?select=title,technical_specs(runtime) HTTP/1.1
|
GET /films?select=title,technical_specs(camera) HTTP/1.1
|
||||||
|
|
||||||
.. code-tab:: bash Curl
|
.. code-tab:: bash Curl
|
||||||
|
|
||||||
curl "http://localhost:3000/films?select=title,technical_specs(runtime)"
|
curl "http://localhost:3000/films?select=title,technical_specs(camera)"
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
@@ -236,20 +269,26 @@ You can manually define relationships between using functions. This is useful fo
|
|||||||
|
|
||||||
Assuming there's a foreign table ``premieres`` that we want to relate to ``films``.
|
Assuming there's a foreign table ``premieres`` that we want to relate to ``films``.
|
||||||
|
|
||||||
.. code-block:: postgres
|
.. tabs::
|
||||||
|
|
||||||
create foreign table premieres (
|
.. group-tab:: ERD
|
||||||
id integer,
|
|
||||||
location text,
|
|
||||||
"date" date,
|
|
||||||
film_id integer
|
|
||||||
) server import_csv options ( filename '/tmp/directors.csv', format 'csv');
|
|
||||||
|
|
||||||
create function film(premieres) returns setof films rows 1 as $$
|
.. image:: ../../_static/premieres.png
|
||||||
select * from films where id = $1.film_id
|
|
||||||
$$ stable language sql;
|
|
||||||
|
|
||||||
The above function defines a relationship between ``premieres`` (the parameter) and ``films`` (the return type). Since there's a ``rows 1``, this defines a many-to-one relationship.
|
.. code-tab:: postgresql SQL
|
||||||
|
|
||||||
|
create foreign table premieres (
|
||||||
|
id integer,
|
||||||
|
location text,
|
||||||
|
"date" date,
|
||||||
|
film_id integer
|
||||||
|
) server import_csv options ( filename '/tmp/directors.csv', format 'csv');
|
||||||
|
|
||||||
|
create function film(premieres) returns setof films rows 1 as $$
|
||||||
|
select * from films where id = $1.film_id
|
||||||
|
$$ stable language sql;
|
||||||
|
|
||||||
|
The above function (see the **SQL** tab) defines a relationship between ``premieres`` (the parameter) and ``films`` (the return type). Since there's a ``rows 1``, this defines a many-to-one relationship.
|
||||||
The name of the function ``film`` is arbitrary and can be used to do the embedding:
|
The name of the function ``film`` is arbitrary and can be used to do the embedding:
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
@@ -698,24 +737,30 @@ Foreign Key joins can also be done between `partitioned tables <https://www.post
|
|||||||
|
|
||||||
For example, let's create the ``box_office`` partitioned table that has the gross daily revenue of a film:
|
For example, let's create the ``box_office`` partitioned table that has the gross daily revenue of a film:
|
||||||
|
|
||||||
.. code-block:: postgres
|
.. tabs::
|
||||||
|
|
||||||
CREATE TABLE box_office (
|
.. group-tab:: ERD
|
||||||
bo_date DATE NOT NULL,
|
|
||||||
film_id INT REFERENCES test.films NOT NULL,
|
|
||||||
gross_revenue DECIMAL(12,2) NOT NULL,
|
|
||||||
PRIMARY KEY (bo_date, film_id)
|
|
||||||
) PARTITION BY RANGE (bo_date);
|
|
||||||
|
|
||||||
-- Let's also create partitions for each month of 2021
|
.. image:: ../../_static/boxoffice.png
|
||||||
|
|
||||||
CREATE TABLE box_office_2021_01 PARTITION OF test.box_office
|
.. code-tab:: postgresql SQL
|
||||||
FOR VALUES FROM ('2021-01-01') TO ('2021-01-31');
|
|
||||||
|
|
||||||
CREATE TABLE box_office_2021_02 PARTITION OF test.box_office
|
CREATE TABLE box_office (
|
||||||
FOR VALUES FROM ('2021-02-01') TO ('2021-02-28');
|
bo_date DATE NOT NULL,
|
||||||
|
film_id INT REFERENCES films NOT NULL,
|
||||||
|
gross_revenue DECIMAL(12,2) NOT NULL,
|
||||||
|
PRIMARY KEY (bo_date, film_id)
|
||||||
|
) PARTITION BY RANGE (bo_date);
|
||||||
|
|
||||||
-- and so until december 2021
|
-- Let's also create partitions for each month of 2021
|
||||||
|
|
||||||
|
CREATE TABLE box_office_2021_01 PARTITION OF box_office
|
||||||
|
FOR VALUES FROM ('2021-01-01') TO ('2021-01-31');
|
||||||
|
|
||||||
|
CREATE TABLE box_office_2021_02 PARTITION OF box_office
|
||||||
|
FOR VALUES FROM ('2021-02-01') TO ('2021-02-28');
|
||||||
|
|
||||||
|
-- and so until december 2021
|
||||||
|
|
||||||
Since it contains the ``films_id`` foreign key, it is possible to join ``box_office`` and ``films``:
|
Since it contains the ``films_id`` foreign key, it is possible to join ``box_office`` and ``films``:
|
||||||
|
|
||||||
|
|||||||