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
|
||||
```
|
||||
|
||||
The fonts used belong to the GNU FreeFont family. You can download them here: http://ftp.gnu.org/gnu/freefont/
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -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]
|
||||
*id
|
||||
first_name
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
entity {font: "FreeSans"}
|
||||
relationship {font: "FreeSerif"}
|
||||
|
||||
[Films]
|
||||
*id
|
||||
+director_id
|
||||
@@ -31,6 +34,12 @@ year
|
||||
*+film_id
|
||||
rank
|
||||
|
||||
[Technical_Specs]
|
||||
*+film_id
|
||||
runtime
|
||||
camera
|
||||
sound
|
||||
|
||||
Roles *--1 Actors
|
||||
Roles *--1 Films
|
||||
|
||||
@@ -38,3 +47,5 @@ Nominations *--1 Competitions
|
||||
Nominations *--1 Films
|
||||
|
||||
Films *--1 Directors
|
||||
|
||||
Films 1--1 Technical_Specs
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Build using: -e ortho
|
||||
|
||||
entity {font: "FreeSans"}
|
||||
relationship {font: "FreeMono"}
|
||||
|
||||
[Addresses]
|
||||
*id
|
||||
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]
|
||||
*id
|
||||
first_name
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Build using: -e ortho
|
||||
|
||||
entity {font: "FreeSans"}
|
||||
relationship {font: "FreeMono"}
|
||||
|
||||
[Users]
|
||||
*id
|
||||
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:
|
||||
|
||||
.. 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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
For the many-to-many relationship between ``films`` and ``actors``, the join table ``roles`` is:
|
||||
|
||||
.. 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)
|
||||
);
|
||||
Thus, it can detect the join table ``roles`` between ``films`` and ``actors``:
|
||||
|
||||
.. 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 relationships
|
||||
@@ -184,38 +228,27 @@ One-to-one relationships
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: postgresql
|
||||
.. code-block:: postgresql
|
||||
|
||||
CREATE TABLE technical_specs(
|
||||
film_id INT REFERENCES films UNIQUE,
|
||||
runtime TIME,
|
||||
camera 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
|
||||
);
|
||||
CREATE TABLE technical_specs(
|
||||
film_id INT REFERENCES films UNIQUE,
|
||||
runtime TIME,
|
||||
camera TEXT,
|
||||
sound TEXT
|
||||
);
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
|
||||
curl "http://localhost:3000/films?select=title,technical_specs(runtime)"
|
||||
curl "http://localhost:3000/films?select=title,technical_specs(camera)"
|
||||
|
||||
.. 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``.
|
||||
|
||||
.. code-block:: postgres
|
||||
.. tabs::
|
||||
|
||||
create foreign table premieres (
|
||||
id integer,
|
||||
location text,
|
||||
"date" date,
|
||||
film_id integer
|
||||
) server import_csv options ( filename '/tmp/directors.csv', format 'csv');
|
||||
.. group-tab:: ERD
|
||||
|
||||
create function film(premieres) returns setof films rows 1 as $$
|
||||
select * from films where id = $1.film_id
|
||||
$$ stable language sql;
|
||||
.. image:: ../../_static/premieres.png
|
||||
|
||||
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:
|
||||
|
||||
.. 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:
|
||||
|
||||
.. code-block:: postgres
|
||||
.. tabs::
|
||||
|
||||
CREATE TABLE box_office (
|
||||
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);
|
||||
.. group-tab:: ERD
|
||||
|
||||
-- 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
|
||||
FOR VALUES FROM ('2021-01-01') TO ('2021-01-31');
|
||||
.. code-tab:: postgresql SQL
|
||||
|
||||
CREATE TABLE box_office_2021_02 PARTITION OF test.box_office
|
||||
FOR VALUES FROM ('2021-02-01') TO ('2021-02-28');
|
||||
CREATE TABLE box_office (
|
||||
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``:
|
||||
|
||||
|
||||