Remove HTTP Snippets

This commit is contained in:
Laurence Isla
2024-01-17 09:07:37 -05:00
committed by GitHub
parent be2778edb5
commit cb5d80aff8
23 changed files with 515 additions and 1787 deletions
+3 -10
View File
@@ -73,17 +73,10 @@ Alternate URL Structure
As discussed in :ref:`singular_plural`, there are no special URL forms for singular resources in PostgREST, only operators for filtering. Thus there are no URLs like :code:`/people/1`. It would be specified instead as
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.object+json
.. code-tab:: bash Curl
curl "http://localhost:3000/people?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
curl "http://localhost:3000/people?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
This allows compound primary keys and makes the intent for singular response independent of a URL convention.
@@ -259,19 +259,11 @@ Test at the REST level
~~~~~~~~~~~~~~~~~~~~~~
An API request to call this function would look like:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "username": "foo", "password": "bar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "username": "foo", "password": "bar" }'
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "username": "foo", "password": "bar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
@@ -296,31 +288,18 @@ Let's add a table, intended for the :code:`foo` user:
Now try to get the table's contents with:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /foobar HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar"
curl "http://localhost:3000/foobar"
This should fail --- of course, we haven't specified the user, thus PostgREST falls back to the :code:`anon` user and denies access.
Add an :code:`Authorization` header. Please use the token value from the login function call above instead of the one provided below.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /foobar HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
curl "http://localhost:3000/foobar" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
This will fail again --- we get :code:`Permission denied to set role`. We forgot to allow the authenticator role to switch into this user by executing:
+4 -12
View File
@@ -199,19 +199,11 @@ the anonymous user :code:`anon` doesn't need permission to read the :code:`basic
An API request to call this function would look like:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "email": "foo@bar.com", "pass": "foobar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "email": "foo@bar.com", "pass": "foobar" }'
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "email": "foo@bar.com", "pass": "foobar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
@@ -25,33 +25,17 @@ You can use the **time zone** to filter or send data if needed.
Suppose you are located in Sydney and want create a report with the date in the local time zone. Your request should look like this:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /reports HTTP/1.1
Content-Type: application/json
[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },
{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]
.. code-tab:: bash Curl
curl "http://localhost:3000/reports" \
-X POST -H "Content-Type: application/json" \
-d '[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]'
curl "http://localhost:3000/reports" \
-X POST -H "Content-Type: application/json" \
-d '[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]'
Someone located in Cairo can retrieve the data using their local time, too:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
.. code-block:: json
@@ -66,15 +50,9 @@ The response has the date in the time zone configured by the server: ``UTC -05:0
You can use other comparative filters and also all the `PostgreSQL special date/time input values <https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-SPECIAL-TABLE>`_ as illustrated in this example:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch)) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
.. code-block:: json
@@ -100,13 +78,11 @@ To work with a ``json`` type column, you can handle the value as a JSON object.
You can insert a new product using a JSON object for the ``extra_info`` column:
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "Canned fish",
@@ -115,21 +91,7 @@ You can insert a new product using a JSON object for the ``extra_info`` column:
"exportable": true
}
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
EOF
EOF
To query and filter the data see :ref:`json_columns` for a complete reference.
@@ -149,61 +111,33 @@ To handle `array types <https://www.postgresql.org/docs/current/arrays.html>`_ y
You can insert a new value using string representation.
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
EOF
EOF
Or you could send the same data using JSON array format:
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
EOF
EOF
To query the data you can use arrow operators. See :ref:`composite_array_columns`.
@@ -220,38 +154,21 @@ Similarly to one-dimensional arrays, both the string representation and JSON arr
You can now update the item using JSON array format:
.. tabs::
.. code-tab:: http
PATCH /movies?id=eq.1 HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies?id=eq.1" \
-X PATCH -H "Content-Type: application/json" \
-d @- << EOF
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?id=eq.1" \
-X PATCH -H "Content-Type: application/json" \
-d @- << EOF
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
EOF
EOF
Then, for example, to query the auditoriums that are located in the first cinema (position 0 in the array) and on the second floor (position 1 in the next inner array), we can use the arrow operators this way:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
.. code-block:: json
@@ -286,57 +203,31 @@ With PostgREST, you have two options to handle `composite type columns <https://
On one hand you can insert values using string representation.
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
EOF
EOF
Or you could insert the same data in JSON format.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
EOF
}
EOF
You can also query the data using arrow operators. See :ref:`composite_array_columns`.
@@ -355,42 +246,23 @@ PostgREST allows you to handle `ranges <https://www.postgresql.org/docs/current/
To insert a new event, specify the ``duration`` value as a string representation of the ``tsrange`` type:
.. tabs::
.. code-tab:: http
POST /events HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/events" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/events" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
EOF
EOF
You can use range :ref:`operators <operators>` to filter the data. But, in this case, requesting a filter like ``events?duration=cs.2023-01-01`` will return an error, because PostgreSQL needs an explicit cast from string to timestamp. A workaround is to use a range starting and ending in the same date:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /events?duration=cs.[2023-01-01,2023-01-01] HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
.. code-block:: json
@@ -428,15 +300,9 @@ Then, create the cast using this function:
Finally, do the request :ref:`casting the range column <casting_columns>`:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /events?select=id,name,duration::json HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?select=id,name,duration::json"
curl "http://localhost:3000/events?select=id,name,duration::json"
.. code-block:: json
@@ -491,20 +357,11 @@ Let's download the PostgREST logo for our test.
Now, to send the file ``postgrest-logo.png`` we need to set the ``Content-Type: application/octet-stream`` header in the request:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/upload_binary HTTP/1.1
Content-Type: application/octet-stream
postgrest-logo.png
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@postgrest-logo.png"
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@postgrest-logo.png"
To get the image from the database, use :ref:`custom_media` like so:
@@ -516,17 +373,10 @@ To get the image from the database, use :ref:`custom_media` like so:
select file from files where id = $1;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /get_image?id=1 HTTP/1.1
Accept: image/png
.. code-tab:: bash Curl
curl "http://localhost:3000/get_image?id=1" \
-H "Accept: image/png"
curl "http://localhost:3000/get_image?id=1" \
-H "Accept: image/png"
See :ref:`providing_img` for a step-by-step example on how to handle images in HTML.
@@ -551,42 +401,24 @@ You can work with data types belonging to additional supplied modules such as `h
The ``name`` column will have the name of the country in different formats. You can insert values using the string representation for that data type:
.. tabs::
.. code-tab:: http
POST /countries HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/countries" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/countries" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
EOF
EOF
Notice that the use of ``"`` in the value of the ``name`` column needs to be escaped using a backslash ``\``.
You can also query and filter the value of a ``hstore`` column using the arrow operators, as you would do for a :ref:`JSON column<json_columns>`. For example, if you want to get the native name of Egypt:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /countries?select=name->>native&name->>common=like.Egypt HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
.. code-block:: json
@@ -612,42 +444,23 @@ You can use the string representation for `PostGIS <https://postgis.net/>`_ data
To add areas in polygon format, you can use string representation:
.. tabs::
.. code-tab:: http
POST /coverage HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/coverage" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
EOF
EOF
Now, when you request the information, PostgREST will automatically cast the ``area`` column into a ``Polygon`` geometry type. Although this is useful, you may need the whole output to be in `GeoJSON <https://geojson.org/>`_ format out of the box, which can be done by including the ``Accept: application/geo+json`` in the request. This will work for PostGIS versions 3.0.0 and up and will return the output as a `FeatureCollection Object <https://www.rfc-editor.org/rfc/rfc7946#section-3.3>`_:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /coverage HTTP/1.1
Accept: application/geo+json
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-H "Accept: application/geo+json"
curl "http://localhost:3000/coverage" \
-H "Accept: application/geo+json"
.. code-block:: json
@@ -711,15 +524,9 @@ In the case that you are using older PostGIS versions, then creating a function
Now this query will return the same results:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/coverage_geo_collection HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/coverage_geo_collection"
curl "http://localhost:3000/rpc/coverage_geo_collection"
.. code-block:: json
+4 -16
View File
@@ -8,27 +8,15 @@ Block Full-Table Operations
If the :ref:`active role <user_impersonation>` can delete table rows then the DELETE verb is allowed for clients. Here's an API request to delete old rows from a hypothetical logs table:
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /logs?time=lt.1991-08-06 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs?time=lt.1991-08-06" -X DELETE
curl "http://localhost:3000/logs?time=lt.1991-08-06" -X DELETE
Note that it's very easy to delete the **entire table** by omitting the query parameter!
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /logs HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs" -X DELETE
curl "http://localhost:3000/logs" -X DELETE
This can happen accidentally such as by switching a request from a GET to a DELETE. To protect against accidental operations use the `pg-safeupdate <https://github.com/eradman/pg-safeupdate>`_ PostgreSQL extension. It raises an error if UPDATE or DELETE are executed without specifying conditions. To install it you can use the `PGXN <https://pgxn.org/>`_ network:
+18 -72
View File
@@ -12,15 +12,9 @@ PostgREST supports the following aggregate functions: ``avg()``, ``count()``, ``
To use an aggregate function, you append the function to a value in the ``select`` parameter, like so:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.sum() HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum()"
curl "http://localhost:3000/orders?select=amount.sum()"
With the above query, PostgREST will return a single row with a single column named ``sum`` that contains the sum of all the values in the ``amount`` column:
@@ -36,15 +30,9 @@ You can use multiple aggregate functions by just adding more columns with aggreg
To group by other columns, you simply add those columns to the ``select`` parameter. For instance:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.sum(),amount.avg(),order_date HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"
curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"
This will return a row for each unique value in the ``order_date`` column, with the sum and average of the ``amount`` column for all rows that share the same ``order_date``:
@@ -75,15 +63,9 @@ The Case of ``count()``
``count()`` is treated specially, as it can be used without an associated column. Take for example the following query:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=count(),order_date HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=count(),order_date"
curl "http://localhost:3000/orders?select=count(),order_date"
This would return a row for each unique value in the ``order_date`` column, with the count of all rows that share the same ``order_date``:
@@ -124,15 +106,9 @@ For instance, imagine that the ``orders`` table has a JSON column, ``order_detai
Therefore, you will need to first cast the input value to a type that is compatible with ``sum()`` (e.g. ``numeric``). Casting the input value is done in exactly the same way as casting any other value:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=order_details->tax_amount::numeric.sum() HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"
curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"
With this, you will receive the sum of the casted ``tax_amount`` value:
@@ -149,15 +125,9 @@ Casting the Value of the Output
Now let's return to an example involving the ``amount`` column of the ``orders`` table. Imagine that we want to get the rounded average of the ``amount`` column. One way to do this is to use the ``avg()`` aggregate function and then to cast the output value of the function to ``int``. To cast the value of the output of the function, we simply place the cast *after* the aggregate function:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.avg()::int HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.avg()::int"
curl "http://localhost:3000/orders?select=amount.avg()::int"
You will then receive the rounded average as the result:
@@ -184,15 +154,9 @@ Using an embedded resource as a grouping column allows you to use data from an a
For example, imagine that the ``orders`` table from the examples above is related to a ``customers`` table. If you want to get the sum of the ``amount`` column grouped by the ``name`` column from the ``customers`` table, you can include the customer name, using the standard :ref:`resource_embedding` syntax, and perform a sum on the ``amount`` column.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.sum(),customers(name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"
curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"
You will then get the summed amount, along with the embedded customer resource:
@@ -223,15 +187,9 @@ When embedding a resource, you can apply aggregate functions to columns from the
Continuing with the example relationship between ``orders`` and ``customers`` from the previous section, imagine that you want to fetch the ``name``, ``city``, and ``state`` for each customer, along with the sum of amount of the customer's orders, grouped by the order date. This can be done in the following way:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /customers?select=name,city,state,orders(amount.sum(),order_date) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
.. code-block:: json
@@ -280,15 +238,9 @@ Grouping with Columns from a Spreaded Resource
For instance, assume you want to sum the ``amount`` column from the ``orders`` table, using the ``city`` and ``state`` columns from the ``customers`` table as grouping columns. To achieve this, you may select these two columns from the ``customers`` table and spread them; they will then be used as grouping columns:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.sum(),...customers(city,state) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)
curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)
The result will be the same as if ``city`` and ``state`` were columns from the ``orders`` table:
@@ -312,15 +264,9 @@ Aggregate Functions with Columns from a Spreaded Resource
Now imagine that the ``customers`` table has a ``joined_date`` column that represents the date that the customer joined. You want to get both the most recent and the oldest ``joined_date`` for customers that placed an order on every distinct order date. This can be expressed as follows:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=order_date,...customers(joined_date.max(),joined_date.min()) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=order_date,...customers(joined_date.max(),joined_date.min())
curl "http://localhost:3000/orders?select=order_date,...customers(joined_date.max(),joined_date.min())
As columns from a spreaded resource are treated as if they were columns from the top-level resource, the ``max()`` and ``min()`` are applied *within* the context of the top-level, rather than within the context of the embedded resource, as in the previous section.
+6 -24
View File
@@ -30,15 +30,9 @@ Horizontal Filtering on Computed Fields
CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?full_name=fts.Beckett HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?full_name=fts.Beckett"
curl "http://localhost:3000/people?full_name=fts.Beckett"
.. code-block:: json
@@ -51,15 +45,9 @@ Vertical Filtering on Computed Fields
Computed fields won't appear on the response by default but you can use :ref:`v_filter` to include them:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=full_name,job HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=full_name,job"
curl "http://localhost:3000/people?select=full_name,job"
.. code-block:: json
@@ -72,15 +60,9 @@ Ordering on Computed Fields
:ref:`ordering` on computed fields is also possible:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?order=full_name.desc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=full_name.desc"
curl "http://localhost:3000/people?order=full_name.desc"
.. important::
+6 -16
View File
@@ -10,22 +10,13 @@ It also handles `preflight requests <https://developer.mozilla.org/en-US/docs/Gl
A ``POST`` preflight request would look like this:
.. tabs::
.. code-block:: bash
.. code-tab:: http
OPTIONS /items HTTP/1.1
Origin: http://example.com
Access-Control-Allow-Method: POST
Access-Control-Allow-Headers: Content-Type
.. code-tab:: bash Curl
curl -i "http://localhost:3000/items" \
-X OPTIONS \
-H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type"
curl -i "http://localhost:3000/items" \
-X OPTIONS \
-H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type"
.. code-block:: http
@@ -47,4 +38,3 @@ With the following config setting, PostgREST will accept CORS requests from doma
.. code-block::
server-cors-allowed-origins="http://example.com, http://example2.com"
+13 -37
View File
@@ -58,17 +58,10 @@ Then create a CAST to tell PostgREST to convert it automatically whenever a JSON
With this you can obtain the data in the shortened format.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /profiles HTTP/1.1
Accept: application/json
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles" \
-H "Accept: application/json"
curl "http://localhost:3000/profiles" \
-H "Accept: application/json"
.. code-block:: json
@@ -102,17 +95,10 @@ PostgREST considers the URL query string to be, in the most generic sense, ``tex
Now you can filter as usual.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /profiles?id=eq.hGxP/ZLOTeeNEY4pkp9OxA== HTTP/1.1
Accept: application/json
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles?id=eq.ZLOTeeNEY4pkp9OxA==" \
-H "Accept: application/json"
curl "http://localhost:3000/profiles?id=eq.ZLOTeeNEY4pkp9OxA==" \
-H "Accept: application/json"
.. code-block:: json
@@ -139,26 +125,16 @@ To accept the shortened format in a JSON request body, for example when creating
Now we can :ref:`insert` (or :ref:`update`) as usual.
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/profiles" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d @- <<JSON
POST /profiles HTTP/1.1
Content-Type: application/json
Prefer: return=representation
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d @- <<JSON
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
JSON
JSON
The response:
+2 -8
View File
@@ -81,15 +81,9 @@ You can override the whole default response with a function result. To do this,
end
$_$ language plpgsql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET / HTTP/1.1
.. code-tab:: bash Curl
curl http://localhost:3000
curl http://localhost:3000
.. code-block:: http
+2 -8
View File
@@ -7,15 +7,9 @@ You can verify which HTTP methods are allowed on endpoints for tables and views
For a table named ``people``, OPTIONS would show:
.. tabs::
.. code-block:: bash
.. code-tab:: http
OPTIONS /people HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people" -X OPTIONS -i
curl "http://localhost:3000/people" -X OPTIONS -i
.. code-block:: http
+20 -64
View File
@@ -23,15 +23,9 @@ Query Parameters
One way to request limits and offsets is by using query parameters. For example:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?limit=15&offset=30 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?limit=15&offset=30"
curl "http://localhost:3000/people?limit=15&offset=30"
This method is also useful for embedded resources, which we will cover in another section. The server always responds with range headers even if you use query parameters to limit the query.
@@ -41,19 +35,11 @@ Range Header
You can use headers to specify the range of rows desired.
This request gets the first twenty people:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
Range-Unit: items
Range: 0-19
.. code-tab:: bash Curl
curl "http://localhost:3000/people" -i \
-H "Range-Unit: items" \
-H "Range: 0-19"
curl "http://localhost:3000/people" -i \
-H "Range-Unit: items" \
-H "Range: 0-19"
Note that the server may respond with fewer if unable to meet your request:
@@ -82,21 +68,12 @@ Exact Count
To get the exact count, use ``Prefer: count=exact``.
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable HTTP/1.1
Range-Unit: items
Range: 0-24
Prefer: count=exact
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable" -I \
-H "Range-Unit: items" \
-H "Range: 0-24" \
-H "Prefer: count=exact"
curl "http://localhost:3000/bigtable" -I \
-H "Range-Unit: items" \
-H "Range: 0-24" \
-H "Prefer: count=exact"
Note that the larger the table the slower this query runs in the database. The server will respond with the selected range and total
@@ -114,17 +91,10 @@ Planned Count
To avoid the shortcomings of :ref:`exact count <exact_count>`, PostgREST can leverage PostgreSQL statistics and get a fairly accurate and fast count.
To do this, specify the ``Prefer: count=planned`` header.
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable?limit=25 HTTP/1.1
Prefer: count=planned
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=planned"
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=planned"
.. code-block:: http
@@ -151,17 +121,10 @@ defined by :ref:`db-max-rows`.
Here's an example. Suppose we set ``db-max-rows=1000`` and ``smalltable`` has 321 rows, then we'll get the exact count:
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /smalltable?limit=25 HTTP/1.1
Prefer: count=estimated
.. code-tab:: bash Curl
curl "http://localhost:3000/smalltable?limit=25" -I \
-H "Prefer: count=estimated"
curl "http://localhost:3000/smalltable?limit=25" -I \
-H "Prefer: count=estimated"
.. code-block:: http
@@ -170,17 +133,10 @@ Here's an example. Suppose we set ``db-max-rows=1000`` and ``smalltable`` has 32
If we make a similar request on ``bigtable``, which has 3573458 rows, we would get the planned count:
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable?limit=25 HTTP/1.1
Prefer: count=estimated
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=estimated"
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=estimated"
.. code-block:: http
+39 -120
View File
@@ -26,17 +26,10 @@ The server ignores unrecognized or unfulfillable preferences by default. You can
``handling=strict`` will throw an error if you specify invalid preferences. For instance:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /projects HTTP/1.1
Prefer: handling=strict, foo, bar
.. code-tab:: bash Curl
curl -i "http://localhost:3000/projects" \
-H "Prefer: handling=strict, foo, bar"
curl -i "http://localhost:3000/projects" \
-H "Prefer: handling=strict, foo, bar"
.. code-block:: http
@@ -55,17 +48,10 @@ The server ignores unrecognized or unfulfillable preferences by default. You can
``handling=lenient`` ignores invalid preferences.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /projects HTTP/1.1
Prefer: handling=lenient, foo, bar
.. code-tab:: bash Curl
curl -i "http://localhost:3000/projects" \
-H "Prefer: handling=lenient, foo, bar"
curl -i "http://localhost:3000/projects" \
-H "Prefer: handling=lenient, foo, bar"
.. code-block:: http
@@ -80,17 +66,10 @@ Timezone
The ``timezone`` preference allows you to change the `PostgreSQL timezone <https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-TIMEZONE>`_. It accepts all timezones in `pg_timezone_names <https://www.postgresql.org/docs/current/view-pg-timezone-names.html>`_.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /timestamps HTTP/1.1
Prefer: timezone=America/Los_Angeles
.. code-tab:: bash Curl
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: timezone=America/Los_Angeles"
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: timezone=America/Los_Angeles"
.. code-block:: http
@@ -108,17 +87,10 @@ The ``timezone`` preference allows you to change the `PostgreSQL timezone <https
For an invalid timezone, PostgREST returns values with the default timezone (configured on ``postgresql.conf`` or as a setting on the :ref:`authenticator <roles>`).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /timestamps HTTP/1.1
Prefer: timezone=Jupiter/Red_Spot
.. code-tab:: bash Curl
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: timezone=Jupiter/Red_Spot"
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: timezone=Jupiter/Red_Spot"
.. code-block:: http
@@ -137,17 +109,10 @@ Note that there's no ``Preference-Applied`` in the response.
However, with ``handling=strict``, an invalid timezone preference will throw an :ref:`error <pgrst122>`.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /timestamps HTTP/1.1
Prefer: handling=strict, timezone=Jupiter/Red_Spot
.. code-tab:: bash Curl
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: handling=strict, timezone=Jupiter/Red_Spot"
curl -i "http://localhost:3000/timestamps" \
-H "Prefer: handling=strict, timezone=Jupiter/Red_Spot"
.. code-block:: http
@@ -171,21 +136,12 @@ Headers Only
If the table has a primary key, the response can contain a :code:`Location` header describing where to find the new object by including the header :code:`Prefer: return=headers-only` in the request. Make sure that the table is not write-only, otherwise constructing the :code:`Location` header will cause a permissions error.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /projects HTTP/1.1
Prefer: return=headers-only
{"id":33, "name": "x"}
.. code-tab:: bash Curl
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: return=headers-only" \
-d '{"id":33, "name": "x"}'
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: return=headers-only" \
-d '{"id":33, "name": "x"}'
.. code-block:: http
@@ -198,22 +154,12 @@ Full
On the other end of the spectrum you can get the full created object back in the response to your request by including the header :code:`Prefer: return=representation`. That way you won't have to make another HTTP call to discover properties that may have been filled in on the server side. You can also apply the standard :ref:`v_filter` to these results.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /projects HTTP/1.1
Content-Type: application/json; charset=utf-8
Prefer: return=representation
{"id":33, "name": "x"}
.. code-tab:: bash Curl
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"id":33, "name": "x"}'
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"id":33, "name": "x"}'
.. code-block:: http
@@ -236,22 +182,12 @@ Transaction End Preference
The ``tx`` preference can be set to specify if the :ref:`transaction <transactions>` will end in a COMMIT or ROLLBACK. This preference is not enabled by default but can be activated with :ref:`db-tx-end`.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /projects HTTP/1.1
Content-Type: application/json
Prefer: tx=rollback, return=representation
{"name": "Project X"}
.. code-tab:: bash Curl
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: tx=rollback, return=representation" \
-d '{"name": "Project X"}'
curl -i "http://localhost:3000/projects" -X POST \
-H "Content-Type: application/json" \
-H "Prefer: tx=rollback, return=representation" \
-d '{"name": "Project X"}'
.. code-block:: http
@@ -270,19 +206,11 @@ You can set a limit to the amount of resources affected in a request by sending
To illustrate the use of this preference, consider the following scenario where the ``items`` table contains 14 rows.
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /items?id=lt.15 HTTP/1.1
Content-Type: application/json; charset=utf-8
Prefer: handling=strict, max-affected=10
.. code-tab:: bash Curl
curl -i "http://localhost:3000/items?id=lt.15 -X DELETE \
-H "Content-Type: application/json" \
-H "Prefer: handling=strict, max-affected=10"
curl -i "http://localhost:3000/items?id=lt.15 -X DELETE \
-H "Content-Type: application/json" \
-H "Prefer: handling=strict, max-affected=10"
.. code-block:: http
@@ -314,21 +242,12 @@ Single JSON object as Function Parameter
SELECT (param->>'x')::int * (param->>'y')::int
$$ LANGUAGE SQL;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/mult_them HTTP/1.1
Prefer: params=single-object
{ "x": 4, "y": 2 }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: params=single-object" \
-d '{ "x": 4, "y": 2 }'
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: params=single-object" \
-d '{ "x": 4, "y": 2 }'
.. code-block:: json
+73 -288
View File
@@ -91,15 +91,9 @@ Many-to-one relationships
Since ``films`` has a **foreign key** to ``directors``, this establishes a many-to-one relationship. This enables us to request all the films and the director for each film.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,directors(id,last_name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,directors(id,last_name)"
curl "http://localhost:3000/films?select=title,directors(id,last_name)"
.. code-block:: json
@@ -128,15 +122,9 @@ Note that the embedded ``directors`` is returned as a JSON object because of the
Since the table name is plural, we can be more accurate by making it singular with an alias.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,director:directors(id,last_name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,director:directors(id,last_name)"
curl "http://localhost:3000/films?select=title,director:directors(id,last_name)"
.. code-block:: json
@@ -157,15 +145,9 @@ One-to-many relationships
The **foreign key reference** establishes the inverse one-to-many relationship. In this case, ``films`` returns as a JSON array because of the “to-many” end.
.. tabs::
.. code-block:: bash
.. 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)"
curl "http://localhost:3000/directors?select=last_name,films(title)"
.. code-block:: json
@@ -206,15 +188,9 @@ The join table is also detected if the composite key has additional columns.
, primary key(id, film_id, actor_id)
);
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /actors?select=first_name,last_name,films(title) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/actors?select=first_name,last_name,films(title)"
curl "http://localhost:3000/actors?select=first_name,last_name,films(title)"
.. code-block:: json
@@ -247,15 +223,9 @@ One-to-one relationships are detected in two ways.
sound TEXT
);
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,technical_specs(camera) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,technical_specs(camera)"
curl "http://localhost:3000/films?select=title,technical_specs(camera)"
.. code-block:: json
@@ -292,15 +262,9 @@ Assuming there's a foreign table ``premieres`` that we want to relate to ``films
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.
The name of the function ``film`` is arbitrary and can be used to do the embedding:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /premieres?select=location,film(name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/premieres?select=location,film(name)"
curl "http://localhost:3000/premieres?select=location,film(name)"
.. code-block:: json
@@ -323,15 +287,9 @@ Now let's define the opposite one-to-many relationship.
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-block:: bash
.. 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)"
curl "http://localhost:3000/films?select=name,premieres(name)"
.. code-block:: json
@@ -417,15 +375,9 @@ For example, suppose you have the following ``orders`` and ``addresses`` tables:
Since the ``orders`` table has two foreign keys to the ``addresses`` table, a foreign key join is ambiguous and PostgREST will respond with an error:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=*,addresses(*) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=*,addresses(*)" -i
curl "http://localhost:3000/orders?select=*,addresses(*)" -i
.. code-block:: http
@@ -455,15 +407,9 @@ Since the ``orders`` table has two foreign keys to the ``addresses`` table, a fo
To successfully join ``orders`` with ``addresses``, we can follow the error ``hint`` which tells us to add the foreign key name as ``!billing`` or ``!shipping``.
Note that the foreign keys have been named explicitly in the :ref:`SQL definition above <multiple_m2o>`. To make the result clearer we'll also alias the tables:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=name,billing_address:addresses!billing(name),shipping_address:addresses!shipping(name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=name,billing_address:addresses!billing(name),shipping_address:addresses!shipping(name)"
curl "http://localhost:3000/orders?select=name,billing_address:addresses!billing(name),shipping_address:addresses!shipping(name)"
.. code-block:: json
@@ -486,15 +432,9 @@ Multiple One-To-Many
Let's take the tables from :ref:`multiple_m2o`. To get the opposite one-to-many relationship, we can also specify the foreign key name:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /addresses?select=name,billing_orders:orders!billing(name),shipping_orders!shipping(name)&id=eq.1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/addresses?select=name,billing_orders:orders!billing(name),shipping_orders!shipping(name)&id=eq.1"
curl "http://localhost:3000/addresses?select=name,billing_orders:orders!billing(name),shipping_orders!shipping(name)&id=eq.1"
.. code-block:: json
@@ -550,15 +490,9 @@ To get either side of the Recursive One-To-One relationship, create the function
Now, to query a president with their predecessor and successor:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /presidents?select=last_name,predecessor(last_name),successor(last_name)&id=eq.2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/presidents?select=last_name,predecessor(last_name),successor(last_name)&id=eq.2"
curl "http://localhost:3000/presidents?select=last_name,predecessor(last_name),successor(last_name)&id=eq.2"
.. code-block:: json
@@ -604,15 +538,9 @@ To get the One-To-Many embedding, that is, the supervisors with their supervisee
Now, the query would be:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /employees?select=last_name,supervisees(last_name)&id=eq.1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/employees?select=last_name,supervisees(last_name)&id=eq.1"
curl "http://localhost:3000/employees?select=last_name,supervisees(last_name)&id=eq.1"
.. code-block:: json
@@ -642,15 +570,9 @@ To get the Many-To-One relationship, that is, the employees with their respectiv
Then, the query would be:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /employees?select=last_name,supervisor(last_name)&id=eq.3 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/employees?select=last_name,supervisor(last_name)&id=eq.3"
curl "http://localhost:3000/employees?select=last_name,supervisor(last_name)&id=eq.3"
.. code-block:: json
@@ -712,15 +634,9 @@ To get all the subscribers of a user as well as the ones they're following, defi
Then, the request would be:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /users?select=username,subscribers(username),following(username)&id=eq.4 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/users?select=username,subscribers(username),following(username)&id=eq.4"
curl "http://localhost:3000/users?select=username,subscribers(username),following(username)&id=eq.4"
.. code-block:: json
@@ -773,15 +689,9 @@ For example, let's create the ``box_office`` partitioned table that has the gros
Since it contains the ``films_id`` foreign key, it is possible to join ``box_office`` and ``films``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /box_office?select=bo_date,gross_revenue,films(title)&gross_revenue=gte.1000000 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/box_office?select=bo_date,gross_revenue,films(title)&gross_revenue=gte.1000000"
curl "http://localhost:3000/box_office?select=bo_date,gross_revenue,films(title)&gross_revenue=gte.1000000"
.. note::
@@ -814,15 +724,9 @@ For instance, the following view has ``nominations``, ``films`` and ``competitio
Since this view contains ``nominations.film_id``, which has a **foreign key** relationship to ``films``, then we can join the ``films`` table. Similarly, because the view contains ``films.id``, then we can also join the ``roles`` and the ``actors`` tables (the last one in a many-to-many relationship):
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /nominations_view?select=film_title,films(language),roles(character),actors(last_name,first_name)&rank=eq.5 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/nominations_view?select=film_title,films(language),roles(character),actors(last_name,first_name)&rank=eq.5"
curl "http://localhost:3000/nominations_view?select=film_title,films(language),roles(character),actors(last_name,first_name)&rank=eq.5"
It's also possible to foreign key join `Materialized Views <https://www.postgresql.org/docs/current/rules-materializedviews.html>`_.
@@ -860,15 +764,9 @@ Here's a sample function (notice the ``RETURNS SETOF films``).
A request with ``directors`` embedded:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/getallfilms?select=title,directors(id,last_name)&title=like.*Workers* HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/getallfilms?select=title,directors(id,last_name)&title=like.*Workers*"
curl "http://localhost:3000/rpc/getallfilms?select=title,directors(id,last_name)&title=like.*Workers*"
.. code-block:: json
@@ -890,36 +788,20 @@ You can join related database objects after doing :ref:`insert`, :ref:`update` o
Say you want to insert a **film** and then get some of its attributes plus join its **director**.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /films?select=title,year,director:directors(first_name,last_name) HTTP/1.1
Prefer: return=representation
{
curl "http://localhost:3000/films?select=title,year,director:directors(first_name,last_name)" \
-H "Prefer: return=representation" \
-d @- << EOF
{
"id": 100,
"director_id": 40,
"title": "127 hours",
"year": 2010,
"rating": 7.6,
"language": "english"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,year,director:directors(first_name,last_name)" \
-H "Prefer: return=representation" \
-d @- << EOF
{
"id": 100,
"director_id": 40,
"title": "127 hours",
"year": 2010,
"rating": 7.6,
"language": "english"
}
EOF
}
EOF
Response:
@@ -941,15 +823,9 @@ Nested Embedding
If you want to embed through join tables but need more control on the intermediate resources, you can do nested embedding. For instance, you can request the Actors, their Roles and the Films for those Roles:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /actors?select=roles(character,films(title,year)) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/actors?select=roles(character,films(title,year))"
curl "http://localhost:3000/actors?select=roles(character,films(title,year))"
.. _embed_filters:
@@ -958,77 +834,41 @@ Embedded Filters
Embedded resources can be shaped similarly to their top-level counterparts. To do so, prefix the query parameters with the name of the embedded resource. For instance, to order the actors in each film:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,actors(*)&actors.order=last_name,first_name HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,actors(*)&actors.order=last_name,first_name"
curl "http://localhost:3000/films?select=*,actors(*)&actors.order=last_name,first_name"
This sorts the list of actors in each film but does *not* change the order of the films themselves. To filter the roles returned with each film:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,roles(*)&roles.character=in.(Chico,Harpo,Groucho) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,roles(*)&roles.character=in.(Chico,Harpo,Groucho)"
curl "http://localhost:3000/films?select=*,roles(*)&roles.character=in.(Chico,Harpo,Groucho)"
Once again, this restricts the roles included to certain characters but does not filter the films in any way. Films without any of those characters would be included along with empty character lists.
An ``or`` filter can be used for a similar operation:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,roles(*)&roles.or=(character.eq.Gummo,character.eq.Zeppo) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,roles(*)&roles.or=(character.eq.Gummo,character.eq.Zeppo)"
curl "http://localhost:3000/films?select=*,roles(*)&roles.or=(character.eq.Gummo,character.eq.Zeppo)"
Limit and offset operations are possible:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,actors(*)&actors.limit=10&actors.offset=2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,actors(*)&actors.limit=10&actors.offset=2"
curl "http://localhost:3000/films?select=*,actors(*)&actors.limit=10&actors.offset=2"
Embedded resources can be aliased and filters can be applied on these aliases:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,90_comps:competitions(name),91_comps:competitions(name)&90_comps.year=eq.1990&91_comps.year=eq.1991 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,90_comps:competitions(name),91_comps:competitions(name)&90_comps.year=eq.1990&91_comps.year=eq.1991"
curl "http://localhost:3000/films?select=*,90_comps:competitions(name),91_comps:competitions(name)&90_comps.year=eq.1990&91_comps.year=eq.1991"
Filters can also be applied on nested embedded resources:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=*,roles(*,actors(*))&roles.actors.order=last_name&roles.actors.first_name=like.*Tom* HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=*,roles(*,actors(*))&roles.actors.order=last_name&roles.actors.first_name=like.*Tom*"
curl "http://localhost:3000/films?select=*,roles(*,actors(*))&roles.actors.order=last_name&roles.actors.first_name=like.*Tom*"
The result will show the nested actors named Tom and order them by last name. Aliases can also be used instead of the resource names to filter the nested tables.
@@ -1039,15 +879,9 @@ Top-level Filtering
By default, :ref:`embed_filters` don't change the top-level resource(``films``) rows at all:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors(first_name,last_name)&actors.first_name=eq.Jehanne HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors(first_name,last_name)&actors.first_name=eq.Jehanne
curl "http://localhost:3000/films?select=title,actors(first_name,last_name)&actors.first_name=eq.Jehanne
.. code-block:: json
@@ -1073,15 +907,9 @@ By default, :ref:`embed_filters` don't change the top-level resource(``films``)
In order to filter the top level rows you need to add ``!inner`` to the embedded resource. For instance, to get **only** the films that have an actor named ``Jehanne``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors!inner(first_name,last_name)&actors.first_name=eq.Jehanne HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors!inner(first_name,last_name)&actors.first_name=eq.Jehanne"
curl "http://localhost:3000/films?select=title,actors!inner(first_name,last_name)&actors.first_name=eq.Jehanne"
.. code-block:: json
@@ -1106,40 +934,22 @@ Null filtering on the embedded resources can behave the same as ``!inner``. Whil
For example, doing ``actors=not.is.null`` returns the same result as ``actors!inner(*)``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors(*)&actors=not.is.null HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors(*)&actors=not.is.null"
curl "http://localhost:3000/films?select=title,actors(*)&actors=not.is.null"
The ``is.null`` filter can be used in embedded resources to perform an anti-join. To get all the films that do not have any nominations:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,nominations()&nominations=is.null HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,nominations()&nominations=is.null"
curl "http://localhost:3000/films?select=title,nominations()&nominations=is.null"
Both ``is.null`` and ``not.is.null`` can be included inside the `or` operator. For instance, to get the films that have no actors **or** directors registered yet:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors(*),directors(*)&or=(actors.is.null,directors.is.null) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors(*),directors(*)&or=(actors.is.null,directors.is.null)"
curl "http://localhost:3000/films?select=title,actors(*),directors(*)&or=(actors.is.null,directors.is.null)"
.. _empty_embed:
@@ -1150,15 +960,9 @@ You can leave an embedded resource empty, this helps with filtering in some case
To filter the films by actors but not include them:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors()&actors.first_name=eq.Jehanne&actors=not.is.null HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors()&actors.first_name=eq.Jehanne&actors=not.is.null"
curl "http://localhost:3000/films?select=title,actors()&actors.first_name=eq.Jehanne&actors=not.is.null"
.. code-block:: json
@@ -1177,15 +981,9 @@ On :ref:`Many-to-One <many-to-one>` and :ref:`One-to-One <one-to-one>` relations
For example, to arrange the films in descending order using the director's last name.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,directors(last_name)&order=directors(last_name).desc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,directors(last_name)&order=directors(last_name).desc"
curl "http://localhost:3000/films?select=title,directors(last_name)&order=directors(last_name).desc"
.. _spread_embed:
@@ -1194,15 +992,9 @@ Spread embedded resource
On many-to-one and one-to-one relationships, you can "spread" the embedded resource. That is, remove the surrounding JSON object for the embedded resource columns.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,...directors(director_last_name:last_name)&title=like.*Workers* HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,...directors(director_last_name:last_name)&title=like.*Workers*"
curl "http://localhost:3000/films?select=title,...directors(director_last_name:last_name)&title=like.*Workers*"
.. code-block:: json
@@ -1217,15 +1009,9 @@ Note that there is no ``"directors"`` object. Also the embed columns can be alia
You can use this to get the columns of a join table in a many-to-many relationship. For instance, to get films and its actors, but including the ``character`` column from the roles table:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /films?select=title,actors:roles(character,...actors(first_name,last_name))&title=like.*Lighthouse* HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/films?select=title,actors:roles(character,...actors(first_name,last_name))&title=like.*Lighthouse*"
curl "http://localhost:3000/films?select=title,actors:roles(character,...actors(first_name,last_name))&title=like.*Lighthouse*"
.. code-block:: json
@@ -1245,4 +1031,3 @@ You can use this to get the columns of a join table in a many-to-many relationsh
.. note::
The spread operator ``...`` is borrowed from the Javascript `spread syntax <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax>`_.
+12 -40
View File
@@ -11,17 +11,10 @@ Response Format
Use the Accept request header to specify the acceptable format (or formats) for the response:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
Accept: application/json
.. code-tab:: bash Curl
curl "http://localhost:3000/people" \
-H "Accept: application/json"
curl "http://localhost:3000/people" \
-H "Accept: application/json"
.. _builtin_media:
@@ -42,17 +35,10 @@ The following vendor media types handlers are also supported.
Any unrecognized media type will throw an error.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
Accept: unknown/unknown
.. code-tab:: bash Curl
curl "http://localhost:3000/people" \
-H "Accept: unknown/unknown"
curl "http://localhost:3000/people" \
-H "Accept: unknown/unknown"
.. code-block:: http
@@ -77,17 +63,10 @@ By default PostgREST returns all JSON results in an array, even when there is on
This can be inconvenient for client code. To return the first result as an object unenclosed by an array, specify :code:`vnd.pgrst.object` as part of the :code:`Accept` header
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /items?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.object+json
.. code-tab:: bash Curl
curl "http://localhost:3000/items?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
curl "http://localhost:3000/items?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
This returns
@@ -131,17 +110,10 @@ By default PostgREST returns all JSON null values. For example, requesting ``/pr
On large result sets, the unused keys with ``null`` values can waste bandwith unnecessarily. To remove them, specify ``nulls=stripped`` as a parameter of ``application/vnd.pgrst.array``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /projects?id=gt.10 HTTP/1.1
Accept: application/vnd.pgrst.array+json;nulls=stripped
.. code-tab:: bash Curl
curl "http://localhost:3000/projects?id=gt.10" \
-H "Accept: application/vnd.pgrst.array+json;nulls=stripped"
curl "http://localhost:3000/projects?id=gt.10" \
-H "Accept: application/vnd.pgrst.array+json;nulls=stripped"
This returns
+11 -36
View File
@@ -42,38 +42,22 @@ GET/HEAD
For GET or HEAD, select the schema with ``Accept-Profile``.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /items HTTP/1.1
Accept-Profile: tenant2
.. code-tab:: bash Curl
curl "http://localhost:3000/items" \
-H "Accept-Profile: tenant2"
curl "http://localhost:3000/items" \
-H "Accept-Profile: tenant2"
Other methods
~~~~~~~~~~~~~
For POST, PATCH, PUT and DELETE, select the schema with ``Content-Profile``.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /items HTTP/1.1
Content-Profile: tenant2
{...}
.. code-tab:: bash Curl
curl "http://localhost:3000/items" \
-X POST -H "Content-Type: application/json" \
-H "Content-Profile: tenant2" \
-d '{...}'
curl "http://localhost:3000/items" \
-X POST -H "Content-Type: application/json" \
-H "Content-Profile: tenant2" \
-d '{...}'
You can also select the schema for :ref:`s_procs` and :ref:`open-api`.
@@ -82,19 +66,10 @@ Restricted schemas
You can only switch to a schema included in :ref:`db-schemas`. Using another schema will result in an error:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /items HTTP/1.1
Accept-Profile: tenant3
{...}
.. code-tab:: bash Curl
curl "http://localhost:3000/items" \
-H "Accept-Profile: tenant3"
curl "http://localhost:3000/items" \
-H "Accept-Profile: tenant3"
.. code-block::
+51 -179
View File
@@ -36,19 +36,11 @@ For instance, assume we have created this function in the database.
The client can call it by posting an object like
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/add_them HTTP/1.1
{ "a": 1, "b": 2 }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "a": 1, "b": 2 }'
curl "http://localhost:3000/rpc/add_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "a": 1, "b": 2 }'
.. code-block:: json
@@ -67,15 +59,9 @@ Calling with GET
If the function doesn't modify the database, it will also run under the GET method (see :ref:`access_mode`).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/add_them?a=1&b=2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
The function parameter names match the JSON object keys in the POST case, for the GET case they match the query parameters ``?a=1&b=2``.
@@ -93,20 +79,11 @@ For this the ``Content-Type: application/json`` header must be included in the r
SELECT ($1->>'x')::int * ($1->>'y')::int
$$ LANGUAGE SQL;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/mult_them HTTP/1.1
Content-Type: application/json
{ "x": 4, "y": 2 }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "x": 4, "y": 2 }'
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "x": 4, "y": 2 }'
.. code-block:: json
@@ -139,20 +116,11 @@ To send raw binary, the parameter type must be ``bytea`` and the header ``Conten
INSERT INTO files(blob) VALUES ($1);
$$ LANGUAGE SQL;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/upload_binary HTTP/1.1
Content-Type: application/octet-stream
file_name.ext
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@file_name.ext"
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@file_name.ext"
.. code-block:: http
@@ -175,20 +143,11 @@ You can call a function that takes an array parameter:
SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/json
{"arr": [1,2,3,4]}
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"arr": [1,2,3,4]}'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"arr": [1,2,3,4]}'
.. code-block:: json
@@ -197,33 +156,19 @@ You can call a function that takes an array parameter:
For calling the function with GET, you can pass the array as an `array literal <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-INPUT>`_,
as in ``{1,2,3,4}``. Note that the curly brackets have to be urlencoded(``{`` is ``%7B`` and ``}`` is ``%7D``).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/plus_one?arr=%7B1,2,3,4%7D' HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"
curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"
.. note::
For versions prior to PostgreSQL 10, to pass a PostgreSQL native array on a POST payload, you need to quote it and use an array literal:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
{ "arr": "{1,2,3,4}" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{ "arr": "{1,2,3,4}" }'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{ "arr": "{1,2,3,4}" }'
In these versions we recommend using function parameters of type JSON to accept arrays from the client.
@@ -240,20 +185,11 @@ You can call a variadic function by passing a JSON array in a POST request:
SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/json
{"v": [1,2,3,4]}
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"v": [1,2,3,4]}'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"v": [1,2,3,4]}'
.. code-block:: json
@@ -261,32 +197,17 @@ You can call a variadic function by passing a JSON array in a POST request:
In a GET request, you can repeat the same parameter name:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/plus_one?v=1&v=2&v=3&v=4 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?v=1&v=2&v=3&v=4"
curl "http://localhost:3000/rpc/plus_one?v=1&v=2&v=3&v=4"
Repeating also works in POST requests with ``Content-Type: application/x-www-form-urlencoded``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/x-www-form-urlencoded
v=1&v=2&v=3&v=4
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'v=1&v=2&v=3&v=4'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'v=1&v=2&v=3&v=4'
.. _table_functions:
@@ -299,25 +220,13 @@ A function that returns a table type can be filtered using the same filters as :
CREATE FUNCTION best_films_2017() RETURNS SETOF films ..
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/rpc/best_films_2017?select=title,director:directors(*)"
GET /rpc/best_films_2017?select=title,director:directors(*) HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017?select=title,director:directors(*)"
.. tabs::
.. code-tab:: http
GET /rpc/best_films_2017?rating=gt.8&order=title.desc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"
.. _function_inlining:
@@ -338,17 +247,10 @@ For example, for the following function:
Let's get its :ref:`explain_plan` when calling it with filters applied:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/getallprojects?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.plan
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
-H "Accept: application/vnd.pgrst.plan"
curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
-H "Accept: application/vnd.pgrst.plan"
.. code-block:: psql
@@ -365,29 +267,17 @@ Scalar functions
PostgREST will detect if the function is scalar or table-valued and will shape the response format accordingly:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/add_them?a=1&b=2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
.. code-block:: json
3
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/best_films_2017 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017"
curl "http://localhost:3000/rpc/best_films_2017"
.. code-block:: json
@@ -412,15 +302,9 @@ Functions that return ``record`` or ``SETOF record`` are supported:
select * from projects;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/projects_setof_record HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/projects_setof_record"
curl "http://localhost:3000/rpc/projects_setof_record"
.. code-block:: json
@@ -443,25 +327,13 @@ You can call overloaded functions with different number of arguments.
CREATE FUNCTION rental_duration(customer_id integer, from_date date) ..
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/rpc/rental_duration?customer_id=232"
GET /rpc/rental_duration?customer_id=232 HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/rental_duration?customer_id=232"
.. tabs::
.. code-tab:: http
GET /rpc/rental_duration?customer_id=232&from_date=2018-07-01 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"
.. important::
+128 -429
View File
@@ -12,15 +12,9 @@ Read
For instance the full contents of a table `people` is returned at
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people"
curl "http://localhost:3000/people"
There are no deeply/nested/routes. Each route provides OPTIONS, GET, HEAD, POST, PATCH, and DELETE verbs depending entirely on database permissions.
@@ -36,27 +30,15 @@ Horizontal Filtering
You can filter result rows by adding conditions on columns. For instance, to return people aged under 13 years old:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?age=lt.13 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?age=lt.13"
curl "http://localhost:3000/people?age=lt.13"
You can evaluate multiple conditions on columns by adding more query string parameters. For instance, to return people who are 18 or older **and** are students:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?age=gte.18&student=is.true HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?age=gte.18&student=is.true"
curl "http://localhost:3000/people?age=gte.18&student=is.true"
.. _operators:
@@ -117,15 +99,9 @@ For more complicated filters you will have to create a new view in the database,
The view will provide a new endpoint:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /fresh_stories HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/fresh_stories"
curl "http://localhost:3000/fresh_stories"
.. _logical_operators:
@@ -134,29 +110,17 @@ Logical operators
Multiple conditions on columns are evaluated using ``AND`` by default, but you can combine them using ``OR`` with the ``or`` operator. For example, to return people under 18 **or** over 21:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?or=(age.lt.18,age.gt.21) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?or=(age.lt.18,age.gt.21)"
curl "http://localhost:3000/people?or=(age.lt.18,age.gt.21)"
To **negate** any operator, you can prefix it with :code:`not` like :code:`?a=not.eq.2` or :code:`?not.and=(a.gte.0,a.lte.100)` .
You can also apply complex logic to the conditions:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?grade=gte.90&student=is.true&or=(age.eq.14,not.and(age.gte.11,age.lte.17)) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?grade=gte.90&student=is.true&or=(age.eq.14,not.and(age.gte.11,age.lte.17))"
curl "http://localhost:3000/people?grade=gte.90&student=is.true&or=(age.eq.14,not.and(age.gte.11,age.lte.17))"
.. _modifiers:
@@ -167,27 +131,15 @@ You may further simplify the logic using the ``any/all`` modifiers of ``eq,like,
For instance, to avoid repeating the same column for ``or``, use ``any`` to get people with last names that start with O or P:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?last_name=like(any).{O*,P*} HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?last_name=like(any).{O*,P*}"
curl "http://localhost:3000/people?last_name=like(any).{O*,P*}"
In a similar way, you can use ``all`` to avoid repeating the same column for ``and``. To get the people with last names that start with O and end with n:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?last_name=like(all).{O*,*n} HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?last_name=like(all).{O*,*n}"
curl "http://localhost:3000/people?last_name=like(all).{O*,*n}"
.. _pattern_matching:
@@ -205,45 +157,21 @@ Full-Text Search
The :code:`fts` filter mentioned above has a number of options to support flexible textual queries, namely the choice of plain vs phrase search and the language used for stemming. Suppose that :code:`tsearch` is a table with column :code:`my_tsv`, of type `tsvector <https://www.postgresql.org/docs/current/datatype-textsearch.html>`_. The following examples illustrate the possibilities.
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/tsearch?my_tsv=fts(french).amusant"
GET /tsearch?my_tsv=fts(french).amusant HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/tsearch?my_tsv=plfts.The%20Fat%20Cats"
curl "http://localhost:3000/tsearch?my_tsv=fts(french).amusant"
.. code-block:: bash
.. tabs::
curl "http://localhost:3000/tsearch?my_tsv=not.phfts(english).The%20Fat%20Cats"
.. code-tab:: http
.. code-block:: bash
GET /tsearch?my_tsv=plfts.The%20Fat%20Cats HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/tsearch?my_tsv=plfts.The%20Fat%20Cats"
.. tabs::
.. code-tab:: http
GET /tsearch?my_tsv=not.phfts(english).The%20Fat%20Cats HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/tsearch?my_tsv=not.phfts(english).The%20Fat%20Cats"
.. tabs::
.. code-tab:: http
GET /tsearch?my_tsv=not.wfts(french).amusant HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/tsearch?my_tsv=not.wfts(french).amusant"
curl "http://localhost:3000/tsearch?my_tsv=not.wfts(french).amusant"
Using `websearch_to_tsquery` requires PostgreSQL of version at least 11.0 and will raise an error in earlier versions of the database.
@@ -254,15 +182,9 @@ Vertical Filtering
When certain columns are wide (such as those holding binary data), it is more efficient for the server to withhold them in a response. The client can specify which columns are required using the :code:`select` parameter.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=first_name,age HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=first_name,age"
curl "http://localhost:3000/people?select=first_name,age"
.. code-block:: json
@@ -280,15 +202,9 @@ Renaming Columns
You can rename the columns by prefixing them with an alias followed by the colon ``:`` operator.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=fullName:full_name,birthDate:birth_date HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=fullName:full_name,birthDate:birth_date"
curl "http://localhost:3000/people?select=fullName:full_name,birthDate:birth_date"
.. code-block:: json
@@ -304,15 +220,9 @@ Casting Columns
Casting the columns is possible by suffixing them with the double colon ``::`` plus the desired type.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=full_name,salary::text HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=full_name,salary::text"
curl "http://localhost:3000/people?select=full_name,salary::text"
.. code-block:: json
@@ -335,15 +245,9 @@ You can specify a path for a ``json`` or ``jsonb`` column using the arrow operat
json_data json
);
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=id,json_data->>blood_type,json_data->phones HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=id,json_data->>blood_type,json_data->phones"
curl "http://localhost:3000/people?select=id,json_data->>blood_type,json_data->phones"
.. code-block:: json
@@ -352,15 +256,9 @@ You can specify a path for a ``json`` or ``jsonb`` column using the arrow operat
{ "id": 2, "blood_type": "O+", "phones": [{"country_code": "43", "number": "512-446-4988"}, {"country_code": "43", "number": "213-891-5979"}] }
]
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=id,json_data->phones->0->>number HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=id,json_data->phones->0->>number"
curl "http://localhost:3000/people?select=id,json_data->phones->0->>number"
.. code-block:: json
@@ -371,15 +269,9 @@ You can specify a path for a ``json`` or ``jsonb`` column using the arrow operat
This also works with filters:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=id,json_data->blood_type&json_data->>blood_type=eq.A- HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=id,json_data->blood_type&json_data->>blood_type=eq.A-"
curl "http://localhost:3000/people?select=id,json_data->blood_type&json_data->>blood_type=eq.A-"
.. code-block:: json
@@ -391,15 +283,9 @@ This also works with filters:
Note that ``->>`` is used to compare ``blood_type`` as ``text``. To compare with an integer value use ``->``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=id,json_data->age&json_data->age=gt.20 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=id,json_data->age&json_data->age=gt.20"
curl "http://localhost:3000/people?select=id,json_data->age&json_data->age=gt.20"
.. code-block:: json
@@ -428,15 +314,9 @@ The arrow operators(``->``, ``->>``) can also be used for accessing composite fi
languages text[]
);
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /countries?select=id,location->>lat,location->>long,primary_language:languages->0&location->lat=gte.19 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/countries?select=id,location->>lat,location->>long,primary_language:languages->0&location->lat=gte.19"
curl "http://localhost:3000/countries?select=id,location->>lat,location->>long,primary_language:languages->0&location->lat=gte.19"
.. code-block:: json
@@ -464,61 +344,31 @@ Ordering
The reserved word ``order`` reorders the response rows. It uses a comma-separated list of columns and directions:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?order=age.desc,height.asc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=age.desc,height.asc"
curl "http://localhost:3000/people?order=age.desc,height.asc"
If no direction is specified it defaults to ascending order:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?order=age HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=age"
curl "http://localhost:3000/people?order=age"
If you care where nulls are sorted, add ``nullsfirst`` or ``nullslast``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/people?order=age.nullsfirst"
GET /people?order=age.nullsfirst HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=age.nullsfirst"
.. tabs::
.. code-tab:: http
GET /people?order=age.desc.nullslast HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=age.desc.nullslast"
curl "http://localhost:3000/people?order=age.desc.nullslast"
You can also sort on fields of :ref:`composite_array_columns` or :ref:`json_columns`.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /countries?order=location->>lat HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/countries?order=location->>lat"
curl "http://localhost:3000/countries?order=location->>lat"
.. _head_req:
@@ -537,19 +387,11 @@ All tables and `auto-updatable views <https://www.postgresql.org/docs/current/sq
To create a row in a database table post a JSON object whose keys are the names of the columns you would like to create. Missing properties will be set to default values when applicable.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /table_name HTTP/1.1
{ "col1": "value1", "col2": "value2" }
.. code-tab:: bash Curl
curl "http://localhost:3000/table_name" \
-X POST -H "Content-Type: application/json" \
-d '{ "col1": "value1", "col2": "value2" }'
curl "http://localhost:3000/table_name" \
-X POST -H "Content-Type: application/json" \
-d '{ "col1": "value1", "col2": "value2" }'
.. code::
@@ -562,20 +404,11 @@ x-www-form-urlencoded
URL encoded payloads can be posted with ``Content-Type: application/x-www-form-urlencoded``.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /people HTTP/1.1
Content-Type: application/x-www-form-urlencoded
name=John+Doe&age=50&weight=80
.. code-tab:: bash Curl
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d "name=John+Doe&age=50&weight=80"
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d "name=John+Doe&age=50&weight=80"
.. note::
@@ -607,53 +440,30 @@ Bulk insert works exactly like single row insert except that you provide either
To bulk insert CSV simply post to a table route with :code:`Content-Type: text/csv` and include the names of the columns as the first row. For instance
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /people HTTP/1.1
Content-Type: text/csv
name,age,height
J Doe,62,70
Jonas,10,55
.. code-tab:: bash Curl
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: text/csv" \
--data-binary @- << EOF
name,age,height
J Doe,62,70
Jonas,10,55
EOF
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: text/csv" \
--data-binary @- << EOF
name,age,height
J Doe,62,70
Jonas,10,55
EOF
An empty field (:code:`,,`) is coerced to an empty string and the reserved word :code:`NULL` is mapped to the SQL null value. Note that there should be no spaces between the column names and commas.
To bulk insert JSON post an array of objects having all-matching keys
.. tabs::
.. code-tab:: http
POST /people HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "name": "J Doe", "age": 62, "height": 70 },
{ "name": "Janus", "age": 10, "height": 55 }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/people" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "name": "J Doe", "age": 62, "height": 70 },
{ "name": "Janus", "age": 10, "height": 55 }
]
EOF
EOF
.. _bulk_insert_default:
@@ -674,50 +484,25 @@ Having:
A request:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /foo?columns=id,bar,baz HTTP/1.1
Content-Type: application/json
Prefer: missing=default, return=representation
[
{ "bar": "val1"
}
, { "bar": "val2"
, "baz": 15
}
]
.. code-tab:: bash Curl
curl "http://localhost:3000/foo?columns=id,bar,baz" \
-H "Content-Type: application/json" \
-H "Prefer: missing=default, return=representation" \
-d @- << EOF
[
{ "bar": "val1"
}
, { "bar": "val2"
, "baz": 15
}
]
EOF
curl "http://localhost:3000/foo?columns=id,bar,baz" \
-H "Content-Type: application/json" \
-H "Prefer: missing=default, return=representation" \
-d @- << EOF
[
{ "bar": "val1" },
{ "bar": "val2", "baz": 15 }
]
EOF
Will result in:
.. code-block:: json
[
{ "id": 1
, "bar": "val1"
, "baz": 100
}
, { "id": 2
, "bar": "val2"
, "baz": 15
}
{ "id": 1, "bar": "val1", "baz": 100 },
{ "id": 2, "bar": "val2", "baz": 15 }
]
.. _specify_columns:
@@ -727,38 +512,21 @@ Specifying Columns
By using the :code:`columns` query parameter it's possible to specify the payload keys that will be inserted and ignore the rest of the payload.
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /datasets?columns=source,publication_date,figure HTTP/1.1
Content-Type: application/json
{
"source": "Natural Disaster Prevention and Control",
"publication_date": "2015-09-11",
"figure": 1100,
"location": "...",
"comment": "...",
"extra": "...",
"stuff": "..."
}
.. code-tab:: bash Curl
curl "http://localhost:3000/datasets?columns=source,publication_date,figure" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"source": "Natural Disaster Prevention and Control",
"publication_date": "2015-09-11",
"figure": 1100,
"location": "...",
"comment": "...",
"extra": "...",
"stuff": "..."
}
EOF
curl "http://localhost:3000/datasets?columns=source,publication_date,figure" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"source": "Natural Disaster Prevention and Control",
"publication_date": "2015-09-11",
"figure": 1100,
"location": "...",
"comment": "...",
"extra": "...",
"stuff": "..."
}
EOF
In this case, only **source**, **publication_date** and **figure** will be inserted. The rest of the JSON keys will be ignored.
@@ -772,19 +540,11 @@ Update
To update a row or rows in a table, use the PATCH verb. Use :ref:`h_filter` to specify which record(s) to update. Here is an example query setting the :code:`category` column to child for all people below a certain age.
.. tabs::
.. code-block:: bash
.. code-tab:: http
PATCH /people?age=lt.13 HTTP/1.1
{ "category": "child" }
.. code-tab:: bash Curl
curl "http://localhost:3000/people?age=lt.13" \
-X PATCH -H "Content-Type: application/json" \
-d '{ "category": "child" }'
curl "http://localhost:3000/people?age=lt.13" \
-X PATCH -H "Content-Type: application/json" \
-d '{ "category": "child" }'
Updates also support :ref:`prefer_return` plus :ref:`v_filter`.
@@ -801,31 +561,18 @@ Upsert
You can make an upsert with :code:`POST` and the :code:`Prefer: resolution=merge-duplicates` header:
.. tabs::
.. code-tab:: http
POST /employees HTTP/1.1
Prefer: resolution=merge-duplicates
.. code-block:: bash
curl "http://localhost:3000/employees" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: resolution=merge-duplicates" \
-d @- << EOF
[
{ "id": 1, "name": "Old employee 1", "salary": 30000 },
{ "id": 2, "name": "Old employee 2", "salary": 42000 },
{ "id": 3, "name": "New employee 3", "salary": 50000 }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/employees" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: resolution=merge-duplicates" \
-d @- << EOF
[
{ "id": 1, "name": "Old employee 1", "salary": 30000 },
{ "id": 2, "name": "Old employee 2", "salary": 42000 },
{ "id": 3, "name": "New employee 3", "salary": 50000 }
]
EOF
EOF
By default, upsert operates based on the primary key columns, you must specify all of them. You can also choose to ignore the duplicates with :code:`Prefer: resolution=ignore-duplicates`. This works best when the primary key is natural, but it's also possible to use it if the primary key is surrogate (example: "id serial primary key"). For more details read `this issue <https://github.com/PostgREST/postgrest/issues/1118>`_.
@@ -839,31 +586,18 @@ On Conflict
By specifying the ``on_conflict`` query parameter, you can make upsert work on a column(s) that has a UNIQUE constraint.
.. tabs::
.. code-tab:: http
POST /employees?on_conflict=name HTTP/1.1
Prefer: resolution=merge-duplicates
.. code-block:: bash
curl "http://localhost:3000/employees?on_conflict=name" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: resolution=merge-duplicates" \
-d @- << EOF
[
{ "name": "Old employee 1", "salary": 40000 },
{ "name": "Old employee 2", "salary": 52000 },
{ "name": "New employee 3", "salary": 60000 }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/employees?on_conflict=name" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: resolution=merge-duplicates" \
-d @- << EOF
[
{ "name": "Old employee 1", "salary": 40000 },
{ "name": "Old employee 2", "salary": 52000 },
{ "name": "New employee 3", "salary": 60000 }
]
EOF
EOF
.. _upsert_put:
@@ -872,19 +606,11 @@ PUT
A single row upsert can be done by using :code:`PUT` and filtering the primary key columns with :code:`eq`:
.. tabs::
.. code-block:: bash
.. code-tab:: http
PUT /employees?id=eq.4 HTTP/1.1
{ "id": 4, "name": "Sara B.", "salary": 60000 }
.. code-tab:: bash Curl
curl "http://localhost/employees?id=eq.4" \
-X PUT -H "Content-Type: application/json" \
-d '{ "id": 4, "name": "Sara B.", "salary": 60000 }'
curl "http://localhost/employees?id=eq.4" \
-X PUT -H "Content-Type: application/json" \
-d '{ "id": 4, "name": "Sara B.", "salary": 60000 }'
All the columns must be specified in the request body, including the primary key columns.
@@ -895,29 +621,16 @@ Delete
To delete rows in a table, use the DELETE verb plus :ref:`h_filter`. For instance deleting inactive users:
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /user?active=is.false HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/user?active=is.false" -X DELETE
curl "http://localhost:3000/user?active=is.false" -X DELETE
Deletions also support :ref:`prefer_return` plus :ref:`v_filter`.
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /user?id=eq.1 HTTP/1.1
Prefer: return=representation
.. code-tab:: bash Curl
curl "http://localhost:3000/user?id=eq.1" -X DELETE \
-H "Prefer: return=representation"
curl "http://localhost:3000/user?id=eq.1" -X DELETE \
-H "Prefer: return=representation"
.. code-block:: json
@@ -934,29 +647,15 @@ Limited Update/Delete
You can limit the amount of affected rows by :ref:`update` or :ref:`delete` with the ``limit`` query parameter. For this, you must add an explicit ``order`` on a unique column(s).
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl -X PATCH "/users?limit=10&order=id&last_login=lt.2020-01-01" \
-H "Content-Type: application/json" \
-d '{ "status": "inactive" }'
PATCH /users?limit=10&order=id&last_login=lt.2017-01-01 HTTP/1.1
.. code-block:: bash
{ "status": "inactive" }
.. code-tab:: bash Curl
curl -X PATCH "/users?limit=10&order=id&last_login=lt.2020-01-01" \
-H "Content-Type: application/json" \
-d '{ "status": "inactive" }'
.. tabs::
.. code-tab:: http
DELETE /users?limit=10&order=id&status=eq.inactive HTTP/1.1
.. code-tab:: bash Curl
curl -X DELETE "http://localhost:3000/users?limit=10&order=id&status=eq.inactive"
curl -X DELETE "http://localhost:3000/users?limit=10&order=id&status=eq.inactive"
If your table has no unique columns, you can use the `ctid <https://www.postgresql.org/docs/current/ddl-system-columns.html>`_ system column.
+10 -41
View File
@@ -31,15 +31,9 @@ To request this:
Do this:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /%D9%85%D9%88%D8%A7%D8%B1%D8%AF HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/%D9%85%D9%88%D8%A7%D8%B1%D8%AF"
curl "http://localhost:3000/%D9%85%D9%88%D8%A7%D8%B1%D8%AF"
.. _tabs-cols-w-spaces:
@@ -48,15 +42,9 @@ Table / Columns with spaces
You can request table/columns with spaces in them by percent encoding the spaces with ``%20``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /Order%20Items?Unit%20Price=lt.200 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/Order%20Items?Unit%20Price=lt.200"
curl "http://localhost:3000/Order%20Items?Unit%20Price=lt.200"
.. _reserved-chars:
@@ -67,44 +55,25 @@ If filters include PostgREST reserved characters(``,``, ``.``, ``:``, ``()``) yo
Here ``Hebdon,John`` and ``Williams,Mary`` are values.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /employees?name=in.(%22Hebdon,John%22,%22Williams,Mary%22) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/employees?name=in.(%22Hebdon,John%22,%22Williams,Mary%22)"
curl "http://localhost:3000/employees?name=in.(%22Hebdon,John%22,%22Williams,Mary%22)"
Here ``information.cpe`` is a column name.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /vulnerabilities?%22information.cpe%22=like.*MS* HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/vulnerabilities?%22information.cpe%22=like.*MS*"
curl "http://localhost:3000/vulnerabilities?%22information.cpe%22=like.*MS*"
If the value filtered by the ``in`` operator has a double quote (``"``), you can escape it using a backslash ``"\""``. A backslash itself can be used with a double backslash ``"\\"``.
Here ``Quote:"`` and ``Backslash:\`` are percent-encoded values. Note that ``%5C`` is the percent-encoded backslash.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /marks?name=in.(%22Quote:%5C%22%22,%22Backslash:%5C%5C%22) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/marks?name=in.(%22Quote:%5C%22%22,%22Backslash:%5C%5C%22)"
curl "http://localhost:3000/marks?name=in.(%22Quote:%5C%22%22,%22Backslash:%5C%5C%22)"
.. note::
Some HTTP libraries might encode URLs automatically(e.g. :code:`axios`). In these cases you should use double quotes
:code:`""` directly instead of :code:`%22`.
+3 -10
View File
@@ -86,17 +86,10 @@ Client Auth
To make an authenticated request the client must include an :code:`Authorization` HTTP header with the value :code:`Bearer <jwt>`. For instance:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /foo HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4
.. code-tab:: bash Curl
curl "http://localhost:3000/foo" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4"
curl "http://localhost:3000/foo" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4"
The ``Bearer`` header value can be used with or without capitalization(``bearer``).
+2 -8
View File
@@ -13,15 +13,9 @@ The ``ready`` endpoint also checks the state of both the Database Connection and
For instance, to verify if PostgREST is running at ``localhost:3000`` while the ``admin-server-port`` is set to ``3001``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET localhost:3001/live HTTP/1.1
.. code-tab:: bash Curl
curl -I "http://localhost:3001/live"
curl -I "http://localhost:3001/live"
.. code-block:: http
+11 -39
View File
@@ -125,18 +125,10 @@ You can enable tracing HTTP requests by setting :ref:`server-trace-header`. Spec
server-trace-header = "X-Request-Id"
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /users HTTP/1.1
X-Request-Id: 123
.. code-tab:: bash Curl
curl "http://localhost:3000/users" \
-H "X-Request-Id: 123"
curl "http://localhost:3000/users" \
-H "X-Request-Id: 123"
.. code::
@@ -151,15 +143,9 @@ Server-Timing Header
You can enable the `Server-Timing <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing>`_ header by setting :ref:`server-timing-enabled` on.
This header communicates metrics of the different phases in the request-response cycle.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /users HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/users" -i
curl "http://localhost:3000/users" -i
.. code::
@@ -186,17 +172,10 @@ Execution plan
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.
This is enabled by :ref:`db-plan-enabled` (false by default).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /users?select=name&order=id HTTP/1.1
Accept: application/vnd.pgrst.plan
.. code-tab:: bash Curl
curl "http://localhost:3000/users?select=name&order=id" \
-H "Accept: application/vnd.pgrst.plan"
curl "http://localhost:3000/users?select=name&order=id" \
-H "Accept: application/vnd.pgrst.plan"
.. code-block:: psql
@@ -205,17 +184,10 @@ This is enabled by :ref:`db-plan-enabled` (false by default).
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::
.. code-block:: bash
.. code-tab:: http
GET /users?select=name&order=id HTTP/1.1
Accept: application/vnd.pgrst.plan+json
.. code-tab:: bash Curl
curl "http://localhost:3000/users?select=name&order=id" \
-H "Accept: application/vnd.pgrst.plan+json"
curl "http://localhost:3000/users?select=name&order=id" \
-H "Accept: application/vnd.pgrst.plan+json"
.. code-block:: json
+7 -26
View File
@@ -30,15 +30,9 @@ Modifying the database inside READ ONLY transactions is not possible. PostgREST
Since the ``callcounter`` view modifies the sequence, calling it with GET or HEAD will result in an error:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /callcounter HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/callcounter"
curl "http://localhost:3000/callcounter"
.. code-block:: http
@@ -246,15 +240,9 @@ You can set the ``response.status`` to override the default status code PostgRES
end;
$$ language plpgsql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/teapot HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/teapot" -i
curl "http://localhost:3000/rpc/teapot" -i
.. code-block:: http
@@ -370,14 +358,7 @@ As an example, let's add some cache headers for all requests that come from an I
Now when you make a GET request to a table or view, you'll get the cache headers.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)
.. code-tab:: bash Curl
curl "http://localhost:3000/people" -i \
-H "User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)"
curl "http://localhost:3000/people" -i \
-H "User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)"