Refine docs for v10
* shorten release page * shorten explain docs * add limited update/delete to release page * refine relationships * refine disambiguation * refine release page * remove migration guide * add author to WWT how-to
This commit is contained in:
+180
-102
@@ -875,52 +875,15 @@ returned together. For example, consider a database of films and their awards:
|
||||
|
||||
.. important::
|
||||
|
||||
* PostgREST needs `FOREIGN KEY constraints <https://www.postgresql.org/docs/current/tutorial-fk.html>`_ to be able to do Resource Embedding.
|
||||
* Whenever FOREIGN KEY constraints change in the database schema you must refresh PostgREST's schema cache for Resource Embedding to work properly. See the section :ref:`schema_reloading`.
|
||||
|
||||
.. _one-to-many:
|
||||
|
||||
One-to-many relationships
|
||||
-------------------------
|
||||
|
||||
When a one-to-many relationship is detected, the embedded resource is returned as a JSON array. For example, we can request the Directors and the Films they directed because there is a foreign key constraint between them, like this:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /directors?select=last_name,films(title) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/directors?select=last_name,films(title)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{ "last_name": "Lumière",
|
||||
"films": [
|
||||
{"title": "Workers Leaving The Lumière Factory In Lyon"}
|
||||
]
|
||||
},
|
||||
{ "last_name": "Dickson",
|
||||
"films": [
|
||||
{"title": "The Dickson Experimental Sound Film"}
|
||||
]
|
||||
},
|
||||
{ "last_name": "Méliès",
|
||||
"films": [
|
||||
{"title": "The Haunted Castle"}
|
||||
]
|
||||
}
|
||||
]
|
||||
Whenever FOREIGN KEY constraints change in the database schema you must refresh PostgREST's schema cache for Resource Embedding to work properly. See the section :ref:`schema_reloading`.
|
||||
|
||||
.. _many-to-one:
|
||||
|
||||
Many-to-one relationships
|
||||
-------------------------
|
||||
|
||||
When a many-to-one relationship is detected, the embedded resource is returned as a JSON object. For example, we can request all the Films and the Director for each film like this:
|
||||
Since ``films`` has a **foreign key** referencing ``directors``, this establishes a many-to-one relationship between them. Because of this, we're able
|
||||
to request all the films and the director for each film.
|
||||
|
||||
.. tabs::
|
||||
|
||||
@@ -955,7 +918,9 @@ When a many-to-one relationship is detected, the embedded resource is returned a
|
||||
}
|
||||
]
|
||||
|
||||
However, the table name is in plural, which is not accurate since a Film is directed by only one Director. Using a table name alias can solve this:
|
||||
Note that the embedded ``directors`` is returned as a JSON object because of the "to-one" end.
|
||||
|
||||
Since the table name is plural, we can be more accurate by making it singular with an alias.
|
||||
|
||||
.. tabs::
|
||||
|
||||
@@ -967,13 +932,64 @@ However, the table name is in plural, which is not accurate since a Film is dire
|
||||
|
||||
curl "http://localhost:3000/films?select=title,director:directors(id,last_name)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{ "title": "Workers Leaving The Lumière Factory In Lyon",
|
||||
"director": {
|
||||
"id": 2,
|
||||
"last_name": "Lumière"
|
||||
}
|
||||
},
|
||||
".."
|
||||
]
|
||||
|
||||
.. _one-to-many:
|
||||
|
||||
One-to-many relationships
|
||||
-------------------------
|
||||
|
||||
The inverse one-to-many relationship between ``directors`` and ``films`` is detected based on the **foreign key** reference. In this case, the embedded ``films`` are returned as a JSON array because of the "to-many" end.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /directors?select=last_name,films(title) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/directors?select=last_name,films(title)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{ "last_name": "Lumière",
|
||||
"films": [
|
||||
{"title": "Workers Leaving The Lumière Factory In Lyon"}
|
||||
]
|
||||
},
|
||||
{ "last_name": "Dickson",
|
||||
"films": [
|
||||
{"title": "The Dickson Experimental Sound Film"}
|
||||
]
|
||||
},
|
||||
{ "last_name": "Méliès",
|
||||
"films": [
|
||||
{"title": "The Haunted Castle"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
.. _many-to-many:
|
||||
|
||||
Many-to-many relationships
|
||||
--------------------------
|
||||
|
||||
PostgREST can also detect many-to-many relationships going through join tables. For this, the join table must contain foreign keys to the tables in
|
||||
the many-to-many relationship and its composite primary key must include these foreign key columns.
|
||||
Many-to-many relationships are detected based on the join table. The join table 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`` would be:
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
@@ -983,8 +999,7 @@ the many-to-many relationship and its composite primary key must include these f
|
||||
, primary key(film_id, actor_id)
|
||||
);
|
||||
|
||||
-- the many-to-many relationship can also be detected if the join table has a surrogate key,
|
||||
-- as long as the foreign key columns are also part of the primary key
|
||||
-- the join table can also be detected if the composite key has additional columns
|
||||
|
||||
create table roles(
|
||||
id int generated always as identity,
|
||||
@@ -993,24 +1008,45 @@ the many-to-many relationship and its composite primary key must include these f
|
||||
, primary key(id, film_id, actor_id)
|
||||
);
|
||||
|
||||
Then you can request the Actors for Films (which in this case finds the information through Roles).
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /actors?select=films(title,year) HTTP/1.1
|
||||
GET /actors?select=first_name,last_name,films(title) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/actors?select=films(title,year)"
|
||||
curl "http://localhost:3000/actors?select=first_name,last_name,films(title)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{ "first_name": "Willem",
|
||||
"last_name": "Dafoe",
|
||||
"films": [
|
||||
{"title": "The Lighthouse"}
|
||||
]
|
||||
},
|
||||
".."
|
||||
]
|
||||
|
||||
.. _one-to-one:
|
||||
|
||||
One-to-one relationships
|
||||
------------------------
|
||||
|
||||
PostgREST detects one-to-one relationships when a foreign key is also the primary key of the table or when the foreign key has a ``UNIQUE`` constraint.
|
||||
one-to-one relationships are detected if there's an unique constraint on a foreign key.
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
CREATE TABLE technical_specs(
|
||||
film_id INT REFERENCES films UNIQUE,
|
||||
runtime TIME,
|
||||
camera TEXT,
|
||||
sound TEXT
|
||||
);
|
||||
|
||||
Or if the foreign key is also a primary key.
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
@@ -1022,66 +1058,117 @@ PostgREST detects one-to-one relationships when a foreign key is also the primar
|
||||
sound TEXT
|
||||
);
|
||||
|
||||
-- references Films using a foreign key with unique constraint
|
||||
CREATE TABLE technical_specs(
|
||||
film_id INT REFERENCES films UNIQUE,
|
||||
runtime TIME,
|
||||
camera TEXT,
|
||||
sound TEXT
|
||||
);
|
||||
|
||||
Now, the embedding between Films and Technical_Specs is returned as a JSON object no matter the order.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=title,technical_specs(*) HTTP/1.1
|
||||
GET /films?select=title,technical_specs(runtime) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/films?select=title,technical_specs(*)"
|
||||
curl "http://localhost:3000/films?select=title,technical_specs(runtime)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{
|
||||
"title": "Pulp Fiction",
|
||||
"technical_specs": {"camera": "Arriflex 35-III"}
|
||||
},
|
||||
".."
|
||||
]
|
||||
|
||||
.. _computed_relationships:
|
||||
|
||||
Computed Relationships
|
||||
Computed relationships
|
||||
----------------------
|
||||
|
||||
You can customize how PostgREST detects relationships between two tables. To do this, you need to create a function that has one of the tables as a single parameter and the other as its return type. For instance:
|
||||
You can manually define relationships between resources. This is useful for database objects that can't define foreign keys, like `Foreign Data Wrappers <https://wiki.postgresql.org/wiki/Foreign_data_wrappers>`_.
|
||||
To do this, you can create functions similar to :ref:`computed_cols`.
|
||||
|
||||
Assuming there's a foreign table ``premieres`` that we want to relate to ``films``.
|
||||
|
||||
.. code-block:: postgres
|
||||
|
||||
CREATE FUNCTION director_competition(directors) RETURNS SETOF competitions AS $$
|
||||
SELECT c.*
|
||||
FROM competitions c
|
||||
JOIN nominations n ON c.id = n.competition_id
|
||||
JOIN films f ON n.film_id = f.id
|
||||
WHERE f.director_id = $1.id
|
||||
$$ STABLE LANGUAGE sql;
|
||||
create foreign table premieres (
|
||||
id integer,
|
||||
location text,
|
||||
"date" date,
|
||||
film_id integer
|
||||
) server import_csv options ( filename '/tmp/directors.csv', format 'csv');
|
||||
|
||||
The above function allows a direct relationship between ``directors`` and ``competitions``:
|
||||
create function film(premieres) returns setof films rows 1 as $$
|
||||
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) and 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::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /directors?select=*,competitions:director_competition(name) HTTP/1.1
|
||||
GET /premieres?select=location,film(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/directors?select=*,competitions:director_competition(name)"
|
||||
curl "http://localhost:3000/premieres?select=location,film(name)"
|
||||
|
||||
Take into consideration that the opposite relationship will not be detected, so you need to create another function for that.
|
||||
.. code-block:: json
|
||||
|
||||
Computed relationships also allow you to override the ones that are detected by default. For example, this function can change the ``/films?select=directors(*)`` embedding:
|
||||
[
|
||||
{
|
||||
"location": "Cannes Film Festival",
|
||||
"film": {"name": "Pulp Fiction"}
|
||||
},
|
||||
".."
|
||||
]
|
||||
|
||||
Now let's define the opposite one-to-many relationship with another function.
|
||||
|
||||
.. code-block:: postgres
|
||||
|
||||
CREATE FUNCTION directors(films) RETURNS SETOF directors ROW 1 AS $$
|
||||
-- Override the relationship here
|
||||
$$ STABLE LANGUAGE sql;
|
||||
create function premieres(films) returns setof premieres as $$
|
||||
select * from premieres where film_id = $1.director_id
|
||||
$$ stable language sql;
|
||||
|
||||
Note that if ``ROW 1`` is added, PostgREST will detect a :ref:`many-to-one relationship <many-to-one>` and return a JSON object instead of an array embedding.
|
||||
Similarly, this function defines a relationship between the parameter ``films`` and the return type ``premieres``.
|
||||
In this case there's an implicit ``ROWS 1000`` defined by PostgreSQL(`search "result_rows" on this PostgreSQL doc <https://www.postgresql.org/docs/current/sql-createfunction.html>`_),
|
||||
we consider any value greater than 1 as "many" so this defines a one-to-many relationship.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=name,premieres(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/films?select=name,premieres(name)"
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{
|
||||
"name": "Pulp Ficiton",
|
||||
"premieres": [{"location": "Cannes Festival"}]
|
||||
},
|
||||
".."
|
||||
]
|
||||
|
||||
Computed relationships also allow you to override the ones that are automatically detected by PostgREST.
|
||||
|
||||
For example, to override the :ref:`many-to-one relationship <many-to-one>` between ``films`` and ``directors``.
|
||||
|
||||
.. code-block:: postgres
|
||||
|
||||
create function directors(films) returns setof directors rows 1 as $$
|
||||
select * from directors where id = $1.director_id
|
||||
$$ stable language sql;
|
||||
|
||||
Taking advantage of overloaded functions, you can use the same function name for different parameters and thus define relationships from other tables/views to ``directors``.
|
||||
|
||||
Computed relationships have good performance as they follow the `Inlining conditions for table functions <https://wiki.postgresql.org/wiki/Inlining_of_SQL_functions#Inlining_conditions_for_table_functions>`_.
|
||||
|
||||
.. _nested_embedding:
|
||||
|
||||
@@ -1327,22 +1414,15 @@ Since this view contains ``nominations.film_id``, which has a **foreign key** re
|
||||
|
||||
It's also possible to embed `Materialized Views <https://www.postgresql.org/docs/current/rules-materializedviews.html>`_.
|
||||
|
||||
.. warning::
|
||||
|
||||
It's not guaranteed that all kinds of views will be embeddable. In particular, views that contain
|
||||
UNIONs will not be made embeddable.
|
||||
|
||||
Why? PostgREST detects source table foreign keys in the view by querying and parsing `pg_rewrite <https://www.postgresql.org/docs/current/catalog-pg-rewrite.html>`_.
|
||||
This may fail depending on the complexity of the view.
|
||||
|
||||
`Report an issue <https://github.com/PostgREST/postgrest/issues>`_ if your view is not made embeddable so we can
|
||||
keep continue improving foreign key detection.
|
||||
|
||||
In the future we'll include a way to manually specify views source foreign keys to address this limitation.
|
||||
|
||||
.. important::
|
||||
|
||||
If view definitions change you must refresh PostgREST's schema cache for this to work properly. See the section :ref:`schema_reloading`.
|
||||
- It's not guaranteed that all kinds of views will be embeddable. In particular, views that contain UNIONs will not be made embeddable.
|
||||
|
||||
+ Why? PostgREST detects source table foreign keys in the view by querying and parsing `pg_rewrite <https://www.postgresql.org/docs/current/catalog-pg-rewrite.html>`_.
|
||||
This may fail depending on the complexity of the view.
|
||||
+ As a workaround, you can use :ref:`computed_relationships` to define manual relationships for views.
|
||||
|
||||
- If view definitions change you must refresh PostgREST's schema cache for this to work properly. See the section :ref:`schema_reloading`.
|
||||
|
||||
.. _embedding_view_chains:
|
||||
|
||||
@@ -1603,7 +1683,7 @@ Hints also work alongside ``!inner`` if a top level filtering is needed. From th
|
||||
|
||||
.. note::
|
||||
|
||||
If the relationship is so complex that hint disambiguation does not solve it, then using :ref:`computed_relationships` is the best alternative.
|
||||
If the relationship is so complex that hint disambiguation does not solve it, you can use :ref:`computed_relationships`.
|
||||
|
||||
.. _insert:
|
||||
|
||||
@@ -2887,9 +2967,7 @@ Returns:
|
||||
Execution plan
|
||||
--------------
|
||||
|
||||
You can get the execution plan of a request by adding the ``Accept: application/vnd.pgrst.plan`` header after setting the :ref:`db-plan-enabled` configuration to ``true``. It is useful to verify why a certain operation might be expensive as a result of using `EXPLAIN <https://www.postgresql.org/docs/current/sql-explain.html>`_ on the generated query for the request.
|
||||
|
||||
The output of the plan is generated in ``text`` format by default:
|
||||
You can get the `EXPLAIN execution plan <https://www.postgresql.org/docs/current/sql-explain.html>`_ of a request by adding the ``Accept: application/vnd.pgrst.plan`` header when :ref:`db-plan-enabled` is set to ``true``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
@@ -2908,7 +2986,7 @@ The output of the plan is generated in ``text`` format by default:
|
||||
Aggregate (cost=73.65..73.68 rows=1 width=112)
|
||||
-> Index Scan using users_pkey on users (cost=0.15..60.90 rows=850 width=36)
|
||||
|
||||
The same execution can be returned in ``json`` format by using the ``Accept: application/vnd.pgrst.plan+json`` header instead:
|
||||
The output of the plan is generated in ``text`` format by default but you can change it to JSON by using the ``+json`` suffix.
|
||||
|
||||
.. tabs::
|
||||
|
||||
@@ -2956,8 +3034,8 @@ The same execution can be returned in ``json`` format by using the ``Accept: app
|
||||
}
|
||||
]
|
||||
|
||||
You can also get the result plan of the different media types that PostgREST supports by adding them to the header using ``for``. For instance, to obtain the plan for a :ref:`text/xml <scalar_return_formats>` media type in json format, you need to add the ``Accept: application/vnd.pgrst.plan; for=text/xml`` header.
|
||||
By default the plan is assumed to generate the JSON representation of a resource(``application/json``), but you can obtain the plan for the :ref:`different representations that PostgREST supports <res_format>` by adding them to the ``for`` parameter. For instance, to obtain the plan for a ``text/xml``, you would use ``Accept: application/vnd.pgrst.plan; for="text/xml``.
|
||||
|
||||
Additionally, the deactivated parameters of the ``EXPLAIN`` command can be enabled by adding them to the header using ``options``. The available parameters are ``analyze``, ``verbose``, ``settings``, ``buffers`` and ``wal``, while the remaining ones are active by default. For example, to add the ``analyze`` and ``wal`` parameters, add the ``Accept: application/vnd.pgrst.plan; options=analyze|wal`` header.
|
||||
The other available parameters are ``analyze``, ``verbose``, ``settings``, ``buffers`` and ``wal``, which correspond to the `EXPLAIN command options <https://www.postgresql.org/docs/current/sql-explain.html>`_. To use the ``analyze`` and ``wal`` parameters for example, you would add them like ``Accept: application/vnd.pgrst.plan; options=analyze|wal``.
|
||||
|
||||
Note that any changes done will be committed when activating the ``analyze`` option. To avoid this, set the :ref:`db-tx-end` configuration in a way that allows to rollback the changes according to your preference.
|
||||
Note that akin to the EXPLAIN command, the changes will be committed when using the ``analyze`` option. To avoid this, you can use the :ref:`db-tx-end` and the ``Prefer: tx=rollback`` header.
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
Working with PostgreSQL data types
|
||||
==================================
|
||||
|
||||
:author: `Laurence Isla <https://github.com/laurenceisla>`_
|
||||
|
||||
PostgREST makes use of PostgreSQL string representations to work with data types. Thanks to this, you can use special values, such as ``now`` for timestamps, ``yes`` for booleans or time values including the time zones. This page describes how you can take advantage of these string representations to perform operations on different PostgreSQL data types.
|
||||
|
||||
.. contents::
|
||||
|
||||
+67
-177
@@ -5,79 +5,65 @@ PostgREST 10.0.0
|
||||
Features
|
||||
--------
|
||||
|
||||
API
|
||||
~~~
|
||||
|
||||
XML/SOAP support for RPC
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
RPC now understands the ``text/xml`` media type, allowing SQL functions to send XML output(``Accept: text/xml``) and receive XML input(``Content-Type: text/xml``). This makes SOAP endpoints possible, check the :ref:`create_soap_endpoint` how-to for more details.
|
||||
RPC now understands the ``text/xml`` media type, allowing SQL functions to send XML output(``Accept: text/xml``) and receive XML input(``Content-Type: text/xml``). This makes SOAP endpoints possible, check the :ref:`create_soap_endpoint` how-to and the :ref:`scalar_return_formats` reference for more details.
|
||||
|
||||
GeoJSON support
|
||||
^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
GeoJSON is supported across the board(reads, writes, RPC) with the ``Accept: application/geo+json`` header, this depends on PostGIS from the versions 3.0.0 and up. The :ref:`working with PostGIS section <ww_postgis>` has an example to get you started.
|
||||
|
||||
One-to-one relationships
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Execution Plan
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
A :ref:`one-to-one relationship <one-to-one>` is now detected when a table's foreign key is also its primary key or when the foreign key has a ``UNIQUE`` constraint.
|
||||
The :ref:`execution plan <explain_plan>` of a request is now obtainable with the ``Accept: application/vnd.pgrst.plan`` header. The result can be in ``text`` or ``json`` formats and is compatible with EXPLAIN vizualizers like `explain.depesz.com <https://explain.depesz.com>`_ or `explain.dalibo.com <https://explain.dalibo.com>`_.
|
||||
|
||||
Customizable Relationships for Resource Embedding
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Resource Embedding
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Using :ref:`computed_relationships`, you can add custom relationships or override automatically detected ones. This makes :ref:`resource_embedding` possible on Foreign Data Wrappers and complex SQL views.
|
||||
- A :ref:`one-to-one relationship <one-to-one>` is now detected when a foreign key is unique.
|
||||
|
||||
EXPLAIN Execution Plan
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
- Using :ref:`computed_relationships`, you can add custom relationships or override automatically detected ones. This makes :ref:`resource_embedding` possible on Foreign Data Wrappers and complex SQL views.
|
||||
|
||||
The :ref:`EXPLAIN execution plan of a request <explain_plan>` is now obtainable with the ``Accept: application/vnd.pgrst.plan`` header. The result can be in ``text`` or ``json`` formats and is compatible with EXPLAIN vizualizers like `explain.depesz.com <https://explain.depesz.com>`_ or `explain.dalibo.com <https://explain.dalibo.com>`_.
|
||||
Horizontal/Vertical Filtering
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
POSIX Regular Expressions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- :ref:`Accessing fields of a Composite type or elements of an Array type <composite_array_columns>` is now possible with the arrow operators(``->``, ``->>``) in the same way you would access a JSON type fields.
|
||||
|
||||
You can now use two :ref:`pattern matching <pattern_matching>` operators for `POSIX regular expressions <https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP>`_: ``match`` and ``imatch``, equivalent in PostgreSQL to ``~`` and ``~*`` respectively.
|
||||
- :ref:`pattern_matching` operators for `POSIX regular expressions <https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP>`_ are now available: ``match`` and ``imatch``, equivalent in PostgreSQL to ``~`` and ``~*`` respectively.
|
||||
|
||||
Access composite type fields and array elements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Insertions/Updates
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:ref:`Accessing fields of a Composite type or elements of an Array type <composite_array_columns>` is now possible with the arrow operators(``->``, ``->>``) in the same way you would access a JSON type fields.
|
||||
- ``limit`` can now affect the number of updated/deleted rows. See :ref:`limited_update_delete`.
|
||||
|
||||
Authorize button for SwaggerUI
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
OpenAPI
|
||||
~~~~~~~
|
||||
|
||||
You can now activate the "Authorize" button in SwaggerUI by enabling the :ref:`openapi-security-active` configuration. Add your JWT token prepending :code:`Bearer` to it and you'll be able to request protected resources.
|
||||
|
||||
Improved error messages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To increase consistency, all the errors messages are now normalized. The ``hint``, ``details``, ``code`` and ``message`` fields will always be present in the body, each one defaulting to a
|
||||
``null`` value. In the same way, the :ref:`errors that were raised <raise_error>` with ``SQLSTATE`` now include the ``message`` and ``code`` in the body.
|
||||
|
||||
To further clarify the source of an error, we now add a ``PGRST`` prefix to the error code of all the errors that are PostgREST-specific and don't come from the database. These errors have unique codes that identifies them and are documented in the :ref:`pgrst_errors` section.
|
||||
|
||||
Administration
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Health checks
|
||||
^^^^^^^^^^^^^
|
||||
- Two :ref:`health check endpoints <health_check>` are now exposed in a secondary port.
|
||||
|
||||
Admins can now benefit from two :ref:`health check endpoints <health_check>` exposed in a different port than the main app. When activated, the ``live`` and ``ready`` endpoints are available to verify if PostgREST is alive and running or if the database connection and the :ref:`schema cache <schema_cache>` are ready for querying.
|
||||
- :ref:`pgrst_logging` now shows the database user.
|
||||
|
||||
Logging users
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
You can now see the :ref:`request database user in the logs <pgrst_logging>`.
|
||||
|
||||
Run without configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is now possible to execute PostgREST without specifying any configuration variable. The three that were mandatory on the previous versions, are no longer so.
|
||||
- It is now possible to execute PostgREST without specifying any configuration variable. The three that were mandatory on the previous versions, are no longer so.
|
||||
|
||||
- If :ref:`db-uri` is not set, PostgREST will use the `libpq environment variables <https://www.postgresql.org/docs/current/libpq-envars.html>`_ for the database connection.
|
||||
- If :ref:`db-schemas` is not set, it will use the database ``public`` schema.
|
||||
- If :ref:`db-anon-role` is not set, it will not allow anonymous requests.
|
||||
|
||||
Error messages
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- To increase consistency, all the errors messages are now normalized. The ``hint``, ``details``, ``code`` and ``message`` fields will always be present in the body, each one defaulting to a ``null`` value. In the same way, the :ref:`errors that were raised <raise_error>` with ``SQLSTATE`` now include the ``message`` and ``code`` in the body.
|
||||
|
||||
- To further clarify the source of an error, we now add a ``PGRST`` prefix to the error code of all the errors that are PostgREST-specific and don't come from the database. These errors have unique codes that identify them and are documented in the :ref:`pgrst_errors` section.
|
||||
|
||||
Documentation improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -95,7 +81,7 @@ Documentation improvements
|
||||
|
||||
* Removed direct links for PostgREST versions older than 8.0 from the versions menu.
|
||||
|
||||
* Removed the deprecated *Embedding table from another schema* how-to.
|
||||
* Removed the *Embedding table from another schema* how-to.
|
||||
|
||||
* Restructured the :ref:`resource_embedding` section:
|
||||
|
||||
@@ -103,6 +89,43 @@ Documentation improvements
|
||||
|
||||
- Renamed the *Embedding through join tables* subsection to :ref:`many-to-many`.
|
||||
|
||||
* Split up the *Insertions/Updates* section into :ref:`insert` and :ref:`update`.
|
||||
|
||||
Breaking changes
|
||||
----------------
|
||||
|
||||
* Many-to-many relationships now require that foreign key columns be part of the join table composite key
|
||||
|
||||
- This was needed to reduce :ref:`embed_disamb` errors in complex schemas(`#2070 <https://github.com/PostgREST/postgrest/issues/2070>`_).
|
||||
|
||||
- For migrating to this version, the less invasive method is to use :ref:`computed_relationships` to replace the previous many-to-many relationships.
|
||||
|
||||
- Otherwise you can change your join table primary key. For example with ``alter table permission_user drop constraint permission_user_pkey, add primary key (id, user_id, permission_id);``
|
||||
|
||||
* Views now are not detected when embedding using :ref:`target_disamb`.
|
||||
|
||||
- This embedding form was easily made ambiguous whenever a new view was added(`#2277 <https://github.com/PostgREST/postgrest/issues/2277>`_).
|
||||
|
||||
- For migrating to this version, you can use :ref:`computed_relationships` to replace the previous view relationships.
|
||||
|
||||
- :ref:`hint_disamb` works as usual on views.
|
||||
|
||||
* ``limit/offset`` now limits the affected rows on ``UPDATE``/``DELETE``
|
||||
|
||||
- Previously, ``limit``/``offset`` only limited the returned rows but not the actual updated rows(`#2156 <https://github.com/PostgREST/postgrest/issues/2156>`_)
|
||||
|
||||
* ``max-rows`` is no longer applied on ``POST``, ``PATCH``, ``PUT`` and ``DELETE`` returned rows
|
||||
|
||||
- This was misleading because the affected rows were not really affected by ``max-rows``, only the returned rows were limited(`#2155 <https://github.com/PostgREST/postgrest/issues/2155>`_)
|
||||
|
||||
* Return ``204 No Content`` without ``Content-Type`` for RPCs returning ``VOID``
|
||||
|
||||
- Previously, those RPCs would return ``null`` as a body with ``Content-Type: application/json`` (`#2001 <https://github.com/PostgREST/postgrest/issues/2001>`_).
|
||||
|
||||
* Using ``Prefer: return=representation`` no longer returns a ``Location`` header
|
||||
|
||||
- This reduces unnecessary computing for all insertions (`#2312 <https://github.com/PostgREST/postgrest/issues/2312>`_)
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
@@ -152,139 +175,6 @@ Bug fixes
|
||||
|
||||
* Allow ``limit=0`` in the request query to return an empty array (`#2269 <https://github.com/PostgREST/postgrest/issues/2269>`_)
|
||||
|
||||
Breaking changes
|
||||
----------------
|
||||
|
||||
* Return ``204 No Content`` without ``Content-Type`` for RPCs returning ``VOID`` (`#2001 <https://github.com/PostgREST/postgrest/issues/2001>`_)
|
||||
|
||||
- Previously, those RPCs would return ``null`` as a body with ``Content-Type: application/json``.
|
||||
|
||||
* ``limit/offset`` now limits the affected rows on ``UPDATE``/``DELETE`` (`#2156 <https://github.com/PostgREST/postgrest/issues/2156>`_)
|
||||
|
||||
- Previously, ``limit``/``offset`` only limited the returned rows but not the actual updated rows
|
||||
|
||||
* ``max-rows`` is no longer applied on ``POST``, ``PATCH``, ``PUT`` and ``DELETE`` returned rows (`#2155 <https://github.com/PostgREST/postgrest/issues/2155>`_)
|
||||
|
||||
- This was misleading because the affected rows were not really affected by ``max-rows``, only the returned rows were limited
|
||||
|
||||
* Restrict generated many-to-many relationships (`#2070 <https://github.com/PostgREST/postgrest/issues/2070>`_)
|
||||
|
||||
- A primary key that contains the foreign key columns is now needed for generating many-to-many relationships.
|
||||
|
||||
* Views now are not detected when embedding using the column or foreign key as target (``/view?select=*,column(*)``) (`#2277 <https://github.com/PostgREST/postgrest/issues/2277>`_)
|
||||
|
||||
- This embedding form was easily made ambiguous whenever a new view was added.
|
||||
|
||||
- For migrating, clients must be updated to the embedding form of ``/view?select=*,other_view!column(*)``.
|
||||
|
||||
* Using ``Prefer: return=representation`` no longer returns a ``Location`` header (`#2312 <https://github.com/PostgREST/postgrest/issues/2312>`_)
|
||||
|
||||
Migration Guide
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Many-to-may relationships
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The way PostgREST infers many-to-many relationships is now restricted. Before this change, a table could work as an intermediate join between two tables just by having foreign keys referencing each one of them. Consider the following:
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
CREATE TABLE users (
|
||||
id INT PRIMARY KEY,
|
||||
name TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE permissions (
|
||||
id INT PRIMARY KEY,
|
||||
name TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE permission_user (
|
||||
id INT PRIMARY KEY,
|
||||
user_id INT REFERENCES users(id),
|
||||
permission_id INT REFERENCES permissions(id)
|
||||
);
|
||||
|
||||
Before, PostgREST could infer a relationship between ``users`` and ``permissions`` through ``permission_user``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /users?select=permissions(*) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/users?select=permissions(*)"
|
||||
|
||||
But now this is not allowed. In order for it to work, the intermediate table must also have the foreign keys included in its primary key. So, in this case we need to do the following:
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
-- This table has a pk defined already so we drop it first
|
||||
alter table permission_user
|
||||
drop constraint permission_user_pkey;
|
||||
|
||||
-- Then we add all the foreign keys to the primary key
|
||||
alter table permission_user
|
||||
add primary key (id, user_id, permission_id);
|
||||
|
||||
With this, PostgREST 10 will infer successfully a relationship between ``users`` and ``permissions``.
|
||||
|
||||
If you want an alternative to the previous method or need a more customized relationship, you could use :ref:`computed_relationships` to get a similar result.
|
||||
|
||||
Embedding views
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Using column names or foreign key constraint names as :ref:`embedding targets <target_disamb>` will not detect views anymore. Consider this as an example:
|
||||
|
||||
.. code-block:: postgresql
|
||||
|
||||
CREATE TABLE users (
|
||||
id INT PRIMARY KEY,
|
||||
name TEXT,
|
||||
is_active BOOL
|
||||
);
|
||||
|
||||
CREATE TABLE messages (
|
||||
id INT PRIMARY KEY,
|
||||
body TEXT,
|
||||
user_id INT REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE VIEW active_users AS
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE is_active;
|
||||
|
||||
Previously, the following request returned a ``300 Multiple Choices`` error, because the ``active_users`` view was also detected:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /messages?select=body,user_id(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000/messages?select=body,user_id(name)"
|
||||
|
||||
But in this version, this will not fail and will embed the table ``users`` instead. You need to use the view name as target in order to embed it, like this:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /messages?select=body,active_users(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
|
||||
curl "http://localhost:3000messages?select=body,active_users(name)"
|
||||
|
||||
For other cases, adding a column or foreign key as :ref:`hint <hint_disamb>` may be needed.
|
||||
|
||||
You could also use :ref:`computed_relationships` to get a similar result or if you want a more customized relationship.
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user