Remove HTTP Snippets
This commit is contained in:
@@ -73,14 +73,7 @@ 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-tab:: http
|
||||
|
||||
GET /people?id=eq.1 HTTP/1.1
|
||||
Accept: application/vnd.pgrst.object+json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?id=eq.1" \
|
||||
-H "Accept: application/vnd.pgrst.object+json"
|
||||
|
||||
@@ -259,15 +259,7 @@ Test at the REST level
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
An API request to call this function would look like:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /rpc/login HTTP/1.1
|
||||
|
||||
{ "username": "foo", "password": "bar" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/login" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -296,13 +288,7 @@ Let's add a table, intended for the :code:`foo` user:
|
||||
|
||||
Now try to get the table's contents with:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /foobar HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/foobar"
|
||||
|
||||
@@ -310,14 +296,7 @@ Now try to get the table's contents with:
|
||||
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-tab:: http
|
||||
|
||||
GET /foobar HTTP/1.1
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/foobar" \
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
|
||||
|
||||
@@ -199,15 +199,7 @@ 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-tab:: http
|
||||
|
||||
POST /rpc/login HTTP/1.1
|
||||
|
||||
{ "email": "foo@bar.com", "pass": "foobar" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/login" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
|
||||
@@ -25,17 +25,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/reports" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -43,13 +33,7 @@ Suppose you are located in Sydney and want create a report with the date in the
|
||||
|
||||
Someone located in Cairo can retrieve the data using their local time, too:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
|
||||
|
||||
@@ -66,13 +50,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
|
||||
|
||||
@@ -100,23 +78,7 @@ 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
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Canned fish",
|
||||
"extra_info": {
|
||||
"expiry_date": "2025-12-31",
|
||||
"exportable": true
|
||||
}
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/products" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -149,21 +111,7 @@ 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
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Paddington",
|
||||
"tags": "{family,comedy,not streamable}",
|
||||
"performance_times": "{12:40,15:00,20:00}"
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/movies" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -178,21 +126,7 @@ You can insert a new value using string representation.
|
||||
|
||||
Or you could send the same data using JSON array format:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /movies HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Paddington",
|
||||
"tags": ["family", "comedy", "not streamable"],
|
||||
"performance_times": ["12:40", "15:00", "20:00"]
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/movies" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -220,18 +154,7 @@ 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
|
||||
|
||||
{
|
||||
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/movies?id=eq.1" \
|
||||
-X PATCH -H "Content-Type: application/json" \
|
||||
@@ -243,13 +166,7 @@ You can now update the item using JSON array format:
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
|
||||
|
||||
@@ -286,16 +203,7 @@ 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
|
||||
|
||||
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/products" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -305,24 +213,7 @@ On one hand you can insert values using string representation.
|
||||
|
||||
Or you could insert the same data in JSON format.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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"
|
||||
}
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/products" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -355,20 +246,7 @@ 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
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "New Year's Party",
|
||||
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/events" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -382,13 +260,7 @@ To insert a new event, specify the ``duration`` value as a string representation
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /events?duration=cs.[2023-01-01,2023-01-01] HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
|
||||
|
||||
@@ -428,13 +300,7 @@ Then, create the cast using this function:
|
||||
|
||||
Finally, do the request :ref:`casting the range column <casting_columns>`:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /events?select=id,name,duration::json HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/events?select=id,name,duration::json"
|
||||
|
||||
@@ -491,16 +357,7 @@ 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-tab:: http
|
||||
|
||||
POST /rpc/upload_binary HTTP/1.1
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
postgrest-logo.png
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/upload_binary" \
|
||||
-X POST -H "Content-Type: application/octet-stream" \
|
||||
@@ -516,14 +373,7 @@ To get the image from the database, use :ref:`custom_media` like so:
|
||||
select file from files where id = $1;
|
||||
$$ language sql;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /get_image?id=1 HTTP/1.1
|
||||
Accept: image/png
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/get_image?id=1" \
|
||||
-H "Accept: image/png"
|
||||
@@ -551,19 +401,7 @@ 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
|
||||
|
||||
[
|
||||
{ "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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/countries" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -578,13 +416,7 @@ Notice that the use of ``"`` in the value of the ``name`` column needs to be esc
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /countries?select=name->>native&name->>common=like.Egypt HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
|
||||
|
||||
@@ -612,19 +444,7 @@ 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
|
||||
|
||||
[
|
||||
{ "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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/coverage" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -637,14 +457,7 @@ To add areas in polygon format, you can use string representation:
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /coverage HTTP/1.1
|
||||
Accept: application/geo+json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/coverage" \
|
||||
-H "Accept: application/geo+json"
|
||||
@@ -711,13 +524,7 @@ In the case that you are using older PostGIS versions, then creating a function
|
||||
|
||||
Now this query will return the same results:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/coverage_geo_collection HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/coverage_geo_collection"
|
||||
|
||||
|
||||
@@ -8,25 +8,13 @@ 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-tab:: http
|
||||
|
||||
DELETE /logs?time=lt.1991-08-06 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
DELETE /logs HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/logs" -X DELETE
|
||||
|
||||
|
||||
@@ -12,13 +12,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=amount.sum() HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=amount.sum()"
|
||||
|
||||
@@ -36,13 +30,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=amount.sum(),amount.avg(),order_date HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"
|
||||
|
||||
@@ -75,13 +63,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=count(),order_date HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=count(),order_date"
|
||||
|
||||
@@ -124,13 +106,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=order_details->tax_amount::numeric.sum() HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"
|
||||
|
||||
@@ -149,13 +125,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=amount.avg()::int HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=amount.avg()::int"
|
||||
|
||||
@@ -184,13 +154,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=amount.sum(),customers(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"
|
||||
|
||||
@@ -223,13 +187,7 @@ 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-tab:: http
|
||||
|
||||
GET /customers?select=name,city,state,orders(amount.sum(),order_date) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
|
||||
|
||||
@@ -280,13 +238,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=amount.sum(),...customers(city,state) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)
|
||||
|
||||
@@ -312,13 +264,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=order_date,...customers(joined_date.max(),joined_date.min()) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=order_date,...customers(joined_date.max(),joined_date.min())
|
||||
|
||||
|
||||
@@ -30,13 +30,7 @@ Horizontal Filtering on Computed Fields
|
||||
CREATE INDEX people_full_name_idx ON people
|
||||
USING GIN (to_tsvector('english', full_name(people)));
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?full_name=fts.Beckett HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?full_name=fts.Beckett"
|
||||
|
||||
@@ -51,13 +45,7 @@ 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-tab:: http
|
||||
|
||||
GET /people?select=full_name,job HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=full_name,job"
|
||||
|
||||
@@ -72,13 +60,7 @@ Ordering on Computed Fields
|
||||
|
||||
:ref:`ordering` on computed fields is also possible:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?order=full_name.desc HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?order=full_name.desc"
|
||||
|
||||
|
||||
@@ -10,16 +10,7 @@ It also handles `preflight requests <https://developer.mozilla.org/en-US/docs/Gl
|
||||
|
||||
A ``POST`` preflight request would look like this:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/items" \
|
||||
-X OPTIONS \
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -58,14 +58,7 @@ 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-tab:: http
|
||||
|
||||
GET /profiles HTTP/1.1
|
||||
Accept: application/json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/profiles" \
|
||||
-H "Accept: application/json"
|
||||
@@ -102,14 +95,7 @@ PostgREST considers the URL query string to be, in the most generic sense, ``tex
|
||||
|
||||
Now you can filter as usual.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /profiles?id=eq.hGxP/ZLOTeeNEY4pkp9OxA== HTTP/1.1
|
||||
Accept: application/json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/profiles?id=eq.ZLOTeeNEY4pkp9OxA==" \
|
||||
-H "Accept: application/json"
|
||||
@@ -139,17 +125,7 @@ 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-tab:: http
|
||||
|
||||
POST /profiles HTTP/1.1
|
||||
Content-Type: application/json
|
||||
Prefer: return=representation
|
||||
|
||||
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/profiles" \
|
||||
-H "Prefer: return=representation" \
|
||||
|
||||
@@ -81,13 +81,7 @@ You can override the whole default response with a function result. To do this,
|
||||
end
|
||||
$_$ language plpgsql;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET / HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl http://localhost:3000
|
||||
|
||||
|
||||
@@ -7,13 +7,7 @@ You can verify which HTTP methods are allowed on endpoints for tables and views
|
||||
|
||||
For a table named ``people``, OPTIONS would show:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
OPTIONS /people HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" -X OPTIONS -i
|
||||
|
||||
|
||||
@@ -23,13 +23,7 @@ Query Parameters
|
||||
|
||||
One way to request limits and offsets is by using query parameters. For example:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?limit=15&offset=30 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?limit=15&offset=30"
|
||||
|
||||
@@ -41,15 +35,7 @@ Range Header
|
||||
You can use headers to specify the range of rows desired.
|
||||
This request gets the first twenty people:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people HTTP/1.1
|
||||
Range-Unit: items
|
||||
Range: 0-19
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" -i \
|
||||
-H "Range-Unit: items" \
|
||||
@@ -82,16 +68,7 @@ Exact Count
|
||||
|
||||
To get the exact count, use ``Prefer: count=exact``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
HEAD /bigtable HTTP/1.1
|
||||
Range-Unit: items
|
||||
Range: 0-24
|
||||
Prefer: count=exact
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/bigtable" -I \
|
||||
-H "Range-Unit: items" \
|
||||
@@ -114,14 +91,7 @@ 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-tab:: http
|
||||
|
||||
HEAD /bigtable?limit=25 HTTP/1.1
|
||||
Prefer: count=planned
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/bigtable?limit=25" -I \
|
||||
-H "Prefer: count=planned"
|
||||
@@ -151,14 +121,7 @@ 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-tab:: http
|
||||
|
||||
HEAD /smalltable?limit=25 HTTP/1.1
|
||||
Prefer: count=estimated
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/smalltable?limit=25" -I \
|
||||
-H "Prefer: count=estimated"
|
||||
@@ -170,14 +133,7 @@ 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-tab:: http
|
||||
|
||||
HEAD /bigtable?limit=25 HTTP/1.1
|
||||
Prefer: count=estimated
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/bigtable?limit=25" -I \
|
||||
-H "Prefer: count=estimated"
|
||||
|
||||
@@ -26,14 +26,7 @@ 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-tab:: http
|
||||
|
||||
GET /projects HTTP/1.1
|
||||
Prefer: handling=strict, foo, bar
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/projects" \
|
||||
-H "Prefer: handling=strict, foo, bar"
|
||||
@@ -55,14 +48,7 @@ The server ignores unrecognized or unfulfillable preferences by default. You can
|
||||
|
||||
``handling=lenient`` ignores invalid preferences.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /projects HTTP/1.1
|
||||
Prefer: handling=lenient, foo, bar
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/projects" \
|
||||
-H "Prefer: handling=lenient, foo, bar"
|
||||
@@ -80,14 +66,7 @@ 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-tab:: http
|
||||
|
||||
GET /timestamps HTTP/1.1
|
||||
Prefer: timezone=America/Los_Angeles
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/timestamps" \
|
||||
-H "Prefer: timezone=America/Los_Angeles"
|
||||
@@ -108,14 +87,7 @@ 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-tab:: http
|
||||
|
||||
GET /timestamps HTTP/1.1
|
||||
Prefer: timezone=Jupiter/Red_Spot
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/timestamps" \
|
||||
-H "Prefer: timezone=Jupiter/Red_Spot"
|
||||
@@ -137,14 +109,7 @@ 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-tab:: http
|
||||
|
||||
GET /timestamps HTTP/1.1
|
||||
Prefer: handling=strict, timezone=Jupiter/Red_Spot
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/timestamps" \
|
||||
-H "Prefer: handling=strict, timezone=Jupiter/Red_Spot"
|
||||
@@ -171,16 +136,7 @@ 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-tab:: http
|
||||
|
||||
POST /projects HTTP/1.1
|
||||
Prefer: return=headers-only
|
||||
|
||||
{"id":33, "name": "x"}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/projects" -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -198,17 +154,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/projects" -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -236,17 +182,7 @@ 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-tab:: http
|
||||
|
||||
POST /projects HTTP/1.1
|
||||
Content-Type: application/json
|
||||
Prefer: tx=rollback, return=representation
|
||||
|
||||
{"name": "Project X"}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/projects" -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -270,15 +206,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl -i "http://localhost:3000/items?id=lt.15 -X DELETE \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -314,16 +242,7 @@ Single JSON object as Function Parameter
|
||||
SELECT (param->>'x')::int * (param->>'y')::int
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /rpc/mult_them HTTP/1.1
|
||||
Prefer: params=single-object
|
||||
|
||||
{ "x": 4, "y": 2 }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/mult_them" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
|
||||
@@ -91,13 +91,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,directors(id,last_name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,directors(id,last_name)"
|
||||
|
||||
@@ -128,13 +122,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,director:directors(id,last_name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,director:directors(id,last_name)"
|
||||
|
||||
@@ -157,13 +145,7 @@ 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-tab:: http
|
||||
|
||||
GET /directors?select=last_name,films(title) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/directors?select=last_name,films(title)"
|
||||
|
||||
@@ -206,13 +188,7 @@ The join table is also detected if the composite key has additional columns.
|
||||
, primary key(id, film_id, actor_id)
|
||||
);
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /actors?select=first_name,last_name,films(title) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/actors?select=first_name,last_name,films(title)"
|
||||
|
||||
@@ -247,13 +223,7 @@ One-to-one relationships are detected in two ways.
|
||||
sound TEXT
|
||||
);
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=title,technical_specs(camera) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,technical_specs(camera)"
|
||||
|
||||
@@ -292,13 +262,7 @@ 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-tab:: http
|
||||
|
||||
GET /premieres?select=location,film(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/premieres?select=location,film(name)"
|
||||
|
||||
@@ -323,13 +287,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=name,premieres(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=name,premieres(name)"
|
||||
|
||||
@@ -417,13 +375,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=*,addresses(*) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=*,addresses(*)" -i
|
||||
|
||||
@@ -455,13 +407,7 @@ 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-tab:: http
|
||||
|
||||
GET /orders?select=name,billing_address:addresses!billing(name),shipping_address:addresses!shipping(name) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/orders?select=name,billing_address:addresses!billing(name),shipping_address:addresses!shipping(name)"
|
||||
|
||||
@@ -486,13 +432,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/addresses?select=name,billing_orders:orders!billing(name),shipping_orders!shipping(name)&id=eq.1"
|
||||
|
||||
@@ -550,13 +490,7 @@ 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-tab:: http
|
||||
|
||||
GET /presidents?select=last_name,predecessor(last_name),successor(last_name)&id=eq.2 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/presidents?select=last_name,predecessor(last_name),successor(last_name)&id=eq.2"
|
||||
|
||||
@@ -604,13 +538,7 @@ To get the One-To-Many embedding, that is, the supervisors with their supervisee
|
||||
|
||||
Now, the query would be:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /employees?select=last_name,supervisees(last_name)&id=eq.1 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/employees?select=last_name,supervisees(last_name)&id=eq.1"
|
||||
|
||||
@@ -642,13 +570,7 @@ To get the Many-To-One relationship, that is, the employees with their respectiv
|
||||
|
||||
Then, the query would be:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /employees?select=last_name,supervisor(last_name)&id=eq.3 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/employees?select=last_name,supervisor(last_name)&id=eq.3"
|
||||
|
||||
@@ -712,13 +634,7 @@ To get all the subscribers of a user as well as the ones they're following, defi
|
||||
|
||||
Then, the request would be:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /users?select=username,subscribers(username),following(username)&id=eq.4 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/users?select=username,subscribers(username),following(username)&id=eq.4"
|
||||
|
||||
@@ -773,13 +689,7 @@ 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-tab:: http
|
||||
|
||||
GET /box_office?select=bo_date,gross_revenue,films(title)&gross_revenue=gte.1000000 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/box_office?select=bo_date,gross_revenue,films(title)&gross_revenue=gte.1000000"
|
||||
|
||||
@@ -814,13 +724,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/nominations_view?select=film_title,films(language),roles(character),actors(last_name,first_name)&rank=eq.5"
|
||||
|
||||
@@ -860,13 +764,7 @@ Here's a sample function (notice the ``RETURNS SETOF films``).
|
||||
|
||||
A request with ``directors`` embedded:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/getallfilms?select=title,directors(id,last_name)&title=like.*Workers* HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/getallfilms?select=title,directors(id,last_name)&title=like.*Workers*"
|
||||
|
||||
@@ -890,23 +788,7 @@ 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-tab:: http
|
||||
|
||||
POST /films?select=title,year,director:directors(first_name,last_name) HTTP/1.1
|
||||
Prefer: return=representation
|
||||
|
||||
{
|
||||
"id": 100,
|
||||
"director_id": 40,
|
||||
"title": "127 hours",
|
||||
"year": 2010,
|
||||
"rating": 7.6,
|
||||
"language": "english"
|
||||
}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,year,director:directors(first_name,last_name)" \
|
||||
-H "Prefer: return=representation" \
|
||||
@@ -941,13 +823,7 @@ 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-tab:: http
|
||||
|
||||
GET /actors?select=roles(character,films(title,year)) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/actors?select=roles(character,films(title,year))"
|
||||
|
||||
@@ -958,25 +834,13 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=*,actors(*)&actors.order=last_name,first_name HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /films?select=*,roles(*)&roles.character=in.(Chico,Harpo,Groucho) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=*,roles(*)&roles.character=in.(Chico,Harpo,Groucho)"
|
||||
|
||||
@@ -984,49 +848,25 @@ Once again, this restricts the roles included to certain characters but does not
|
||||
|
||||
An ``or`` filter can be used for a similar operation:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=*,roles(*)&roles.or=(character.eq.Gummo,character.eq.Zeppo) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=*,roles(*)&roles.or=(character.eq.Gummo,character.eq.Zeppo)"
|
||||
|
||||
Limit and offset operations are possible:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=*,actors(*)&actors.limit=10&actors.offset=2 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-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
|
||||
.. code-block:: bash
|
||||
|
||||
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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=*,roles(*,actors(*))&roles.actors.order=last_name&roles.actors.first_name=like.*Tom*"
|
||||
|
||||
@@ -1039,13 +879,7 @@ Top-level Filtering
|
||||
|
||||
By default, :ref:`embed_filters` don't change the top-level resource(``films``) rows at all:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /films?select=title,actors(first_name,last_name)&actors.first_name=eq.Jehanne HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,actors(first_name,last_name)&actors.first_name=eq.Jehanne
|
||||
|
||||
@@ -1073,13 +907,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,actors!inner(first_name,last_name)&actors.first_name=eq.Jehanne HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,actors!inner(first_name,last_name)&actors.first_name=eq.Jehanne"
|
||||
|
||||
@@ -1106,38 +934,20 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,actors(*)&actors=not.is.null HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /films?select=title,nominations()&nominations=is.null HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /films?select=title,actors(*),directors(*)&or=(actors.is.null,directors.is.null) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,actors(*),directors(*)&or=(actors.is.null,directors.is.null)"
|
||||
|
||||
@@ -1150,13 +960,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,actors()&actors.first_name=eq.Jehanne&actors=not.is.null HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,actors()&actors.first_name=eq.Jehanne&actors=not.is.null"
|
||||
|
||||
@@ -1177,13 +981,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,directors(last_name)&order=directors(last_name).desc HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,directors(last_name)&order=directors(last_name).desc"
|
||||
|
||||
@@ -1194,13 +992,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,...directors(director_last_name:last_name)&title=like.*Workers* HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,...directors(director_last_name:last_name)&title=like.*Workers*"
|
||||
|
||||
@@ -1217,13 +1009,7 @@ 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-tab:: http
|
||||
|
||||
GET /films?select=title,actors:roles(character,...actors(first_name,last_name))&title=like.*Lighthouse* HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/films?select=title,actors:roles(character,...actors(first_name,last_name))&title=like.*Lighthouse*"
|
||||
|
||||
@@ -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>`_.
|
||||
|
||||
|
||||
@@ -11,14 +11,7 @@ Response Format
|
||||
|
||||
Use the Accept request header to specify the acceptable format (or formats) for the response:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people HTTP/1.1
|
||||
Accept: application/json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" \
|
||||
-H "Accept: application/json"
|
||||
@@ -42,14 +35,7 @@ The following vendor media types handlers are also supported.
|
||||
|
||||
Any unrecognized media type will throw an error.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people HTTP/1.1
|
||||
Accept: unknown/unknown
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" \
|
||||
-H "Accept: unknown/unknown"
|
||||
@@ -77,14 +63,7 @@ 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-tab:: http
|
||||
|
||||
GET /items?id=eq.1 HTTP/1.1
|
||||
Accept: application/vnd.pgrst.object+json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/items?id=eq.1" \
|
||||
-H "Accept: application/vnd.pgrst.object+json"
|
||||
@@ -131,14 +110,7 @@ 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-tab:: http
|
||||
|
||||
GET /projects?id=gt.10 HTTP/1.1
|
||||
Accept: application/vnd.pgrst.array+json;nulls=stripped
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/projects?id=gt.10" \
|
||||
-H "Accept: application/vnd.pgrst.array+json;nulls=stripped"
|
||||
|
||||
@@ -42,14 +42,7 @@ GET/HEAD
|
||||
|
||||
For GET or HEAD, select the schema with ``Accept-Profile``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /items HTTP/1.1
|
||||
Accept-Profile: tenant2
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/items" \
|
||||
-H "Accept-Profile: tenant2"
|
||||
@@ -59,16 +52,7 @@ Other methods
|
||||
|
||||
For POST, PATCH, PUT and DELETE, select the schema with ``Content-Profile``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /items HTTP/1.1
|
||||
Content-Profile: tenant2
|
||||
|
||||
{...}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/items" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -82,16 +66,7 @@ Restricted schemas
|
||||
|
||||
You can only switch to a schema included in :ref:`db-schemas`. Using another schema will result in an error:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /items HTTP/1.1
|
||||
Accept-Profile: tenant3
|
||||
|
||||
{...}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/items" \
|
||||
-H "Accept-Profile: tenant3"
|
||||
|
||||
@@ -36,15 +36,7 @@ For instance, assume we have created this function in the database.
|
||||
|
||||
The client can call it by posting an object like
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /rpc/add_them HTTP/1.1
|
||||
|
||||
{ "a": 1, "b": 2 }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/add_them" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -67,13 +59,7 @@ 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-tab:: http
|
||||
|
||||
GET /rpc/add_them?a=1&b=2 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
|
||||
|
||||
@@ -93,16 +79,7 @@ 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-tab:: http
|
||||
|
||||
POST /rpc/mult_them HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{ "x": 4, "y": 2 }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/mult_them" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -139,16 +116,7 @@ To send raw binary, the parameter type must be ``bytea`` and the header ``Conten
|
||||
INSERT INTO files(blob) VALUES ($1);
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /rpc/upload_binary HTTP/1.1
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
file_name.ext
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/upload_binary" \
|
||||
-X POST -H "Content-Type: application/octet-stream" \
|
||||
@@ -175,16 +143,7 @@ You can call a function that takes an array parameter:
|
||||
SELECT array_agg(n + 1) FROM unnest($1) AS n;
|
||||
$$ language sql;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
POST /rpc/plus_one HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{"arr": [1,2,3,4]}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/plus_one" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -197,13 +156,7 @@ 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-tab:: http
|
||||
|
||||
GET /rpc/plus_one?arr=%7B1,2,3,4%7D' HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"
|
||||
|
||||
@@ -211,15 +164,7 @@ as in ``{1,2,3,4}``. Note that the curly brackets have to be urlencoded(``{`` is
|
||||
|
||||
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-tab:: http
|
||||
|
||||
POST /rpc/plus_one HTTP/1.1
|
||||
|
||||
{ "arr": "{1,2,3,4}" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/plus_one" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -240,16 +185,7 @@ 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-tab:: http
|
||||
|
||||
POST /rpc/plus_one HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{"v": [1,2,3,4]}
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/plus_one" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -261,28 +197,13 @@ 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-tab:: http
|
||||
|
||||
GET /rpc/plus_one?v=1&v=2&v=3&v=4 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/plus_one" \
|
||||
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
|
||||
@@ -299,23 +220,11 @@ 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-tab:: http
|
||||
|
||||
GET /rpc/best_films_2017?select=title,director:directors(*) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"
|
||||
|
||||
@@ -338,14 +247,7 @@ For example, for the following function:
|
||||
|
||||
Let's get its :ref:`explain_plan` when calling it with filters applied:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/getallprojects?id=eq.1 HTTP/1.1
|
||||
Accept: application/vnd.pgrst.plan
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
|
||||
-H "Accept: application/vnd.pgrst.plan"
|
||||
@@ -365,13 +267,7 @@ Scalar functions
|
||||
|
||||
PostgREST will detect if the function is scalar or table-valued and will shape the response format accordingly:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/add_them?a=1&b=2 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
|
||||
|
||||
@@ -379,13 +275,7 @@ PostgREST will detect if the function is scalar or table-valued and will shape t
|
||||
|
||||
3
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/best_films_2017 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/best_films_2017"
|
||||
|
||||
@@ -412,13 +302,7 @@ Functions that return ``record`` or ``SETOF record`` are supported:
|
||||
select * from projects;
|
||||
$$ language sql;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/projects_setof_record HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/projects_setof_record"
|
||||
|
||||
@@ -443,23 +327,11 @@ You can call overloaded functions with different number of arguments.
|
||||
|
||||
CREATE FUNCTION rental_duration(customer_id integer, from_date date) ..
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/rental_duration?customer_id=232 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"
|
||||
|
||||
|
||||
@@ -12,13 +12,7 @@ Read
|
||||
|
||||
For instance the full contents of a table `people` is returned at
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people"
|
||||
|
||||
@@ -36,25 +30,13 @@ Horizontal Filtering
|
||||
|
||||
You can filter result rows by adding conditions on columns. For instance, to return people aged under 13 years old:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?age=lt.13 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /people?age=gte.18&student=is.true HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?age=gte.18&student=is.true"
|
||||
|
||||
@@ -117,13 +99,7 @@ For more complicated filters you will have to create a new view in the database,
|
||||
|
||||
The view will provide a new endpoint:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /fresh_stories HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/fresh_stories"
|
||||
|
||||
@@ -134,13 +110,7 @@ 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-tab:: http
|
||||
|
||||
GET /people?or=(age.lt.18,age.gt.21) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?or=(age.lt.18,age.gt.21)"
|
||||
|
||||
@@ -148,13 +118,7 @@ To **negate** any operator, you can prefix it with :code:`not` like :code:`?a=no
|
||||
|
||||
You can also apply complex logic to the conditions:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?grade=gte.90&student=is.true&or=(age.eq.14,not.and(age.gte.11,age.lte.17))"
|
||||
|
||||
@@ -167,25 +131,13 @@ 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-tab:: http
|
||||
|
||||
GET /people?last_name=like(any).{O*,P*} HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /people?last_name=like(all).{O*,*n} HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?last_name=like(all).{O*,*n}"
|
||||
|
||||
@@ -205,43 +157,19 @@ 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-tab:: http
|
||||
|
||||
GET /tsearch?my_tsv=fts(french).amusant HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/tsearch?my_tsv=fts(french).amusant"
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /tsearch?my_tsv=plfts.The%20Fat%20Cats HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/tsearch?my_tsv=not.wfts(french).amusant"
|
||||
|
||||
@@ -254,13 +182,7 @@ 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-tab:: http
|
||||
|
||||
GET /people?select=first_name,age HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=first_name,age"
|
||||
|
||||
@@ -280,13 +202,7 @@ Renaming Columns
|
||||
|
||||
You can rename the columns by prefixing them with an alias followed by the colon ``:`` operator.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?select=fullName:full_name,birthDate:birth_date HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=fullName:full_name,birthDate:birth_date"
|
||||
|
||||
@@ -304,13 +220,7 @@ Casting Columns
|
||||
|
||||
Casting the columns is possible by suffixing them with the double colon ``::`` plus the desired type.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?select=full_name,salary::text HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=full_name,salary::text"
|
||||
|
||||
@@ -335,13 +245,7 @@ You can specify a path for a ``json`` or ``jsonb`` column using the arrow operat
|
||||
json_data json
|
||||
);
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?select=id,json_data->>blood_type,json_data->phones HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=id,json_data->>blood_type,json_data->phones"
|
||||
|
||||
@@ -352,13 +256,7 @@ 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-tab:: http
|
||||
|
||||
GET /people?select=id,json_data->phones->0->>number HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=id,json_data->phones->0->>number"
|
||||
|
||||
@@ -371,13 +269,7 @@ You can specify a path for a ``json`` or ``jsonb`` column using the arrow operat
|
||||
|
||||
This also works with filters:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?select=id,json_data->blood_type&json_data->>blood_type=eq.A- HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=id,json_data->blood_type&json_data->>blood_type=eq.A-"
|
||||
|
||||
@@ -391,13 +283,7 @@ This also works with filters:
|
||||
|
||||
Note that ``->>`` is used to compare ``blood_type`` as ``text``. To compare with an integer value use ``->``:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?select=id,json_data->age&json_data->age=gt.20 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?select=id,json_data->age&json_data->age=gt.20"
|
||||
|
||||
@@ -428,13 +314,7 @@ The arrow operators(``->``, ``->>``) can also be used for accessing composite fi
|
||||
languages text[]
|
||||
);
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/countries?select=id,location->>lat,location->>long,primary_language:languages->0&location->lat=gte.19"
|
||||
|
||||
@@ -464,59 +344,29 @@ Ordering
|
||||
|
||||
The reserved word ``order`` reorders the response rows. It uses a comma-separated list of columns and directions:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?order=age.desc,height.asc HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?order=age.desc,height.asc"
|
||||
|
||||
If no direction is specified it defaults to ascending order:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?order=age HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?order=age"
|
||||
|
||||
If you care where nulls are sorted, add ``nullsfirst`` or ``nullslast``:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /people?order=age.nullsfirst HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
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-tab:: http
|
||||
|
||||
GET /countries?order=location->>lat HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/countries?order=location->>lat"
|
||||
|
||||
@@ -537,15 +387,7 @@ 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-tab:: http
|
||||
|
||||
POST /table_name HTTP/1.1
|
||||
|
||||
{ "col1": "value1", "col2": "value2" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/table_name" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -562,16 +404,7 @@ x-www-form-urlencoded
|
||||
|
||||
URL encoded payloads can be posted with ``Content-Type: application/x-www-form-urlencoded``.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" \
|
||||
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
|
||||
@@ -607,18 +440,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" \
|
||||
-X POST -H "Content-Type: text/csv" \
|
||||
@@ -632,19 +454,7 @@ An empty field (:code:`,,`) is coerced to an empty string and the reserved word
|
||||
|
||||
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
|
||||
|
||||
[
|
||||
{ "name": "J Doe", "age": 62, "height": 70 },
|
||||
{ "name": "Janus", "age": 10, "height": 55 }
|
||||
]
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -674,34 +484,15 @@ Having:
|
||||
|
||||
A request:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. 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
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
}
|
||||
{ "bar": "val1" },
|
||||
{ "bar": "val2", "baz": 15 }
|
||||
]
|
||||
EOF
|
||||
|
||||
@@ -710,14 +501,8 @@ 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,24 +512,7 @@ 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-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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/datasets?columns=source,publication_date,figure" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -772,15 +540,7 @@ 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-tab:: http
|
||||
|
||||
PATCH /people?age=lt.13 HTTP/1.1
|
||||
|
||||
{ "category": "child" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people?age=lt.13" \
|
||||
-X PATCH -H "Content-Type: application/json" \
|
||||
@@ -801,20 +561,7 @@ 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
|
||||
|
||||
[
|
||||
{ "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
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/employees" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -839,20 +586,7 @@ 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
|
||||
|
||||
[
|
||||
{ "name": "Old employee 1", "salary": 40000 },
|
||||
{ "name": "Old employee 2", "salary": 52000 },
|
||||
{ "name": "New employee 3", "salary": 60000 }
|
||||
]
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/employees?on_conflict=name" \
|
||||
-X POST -H "Content-Type: application/json" \
|
||||
@@ -872,15 +606,7 @@ PUT
|
||||
|
||||
A single row upsert can be done by using :code:`PUT` and filtering the primary key columns with :code:`eq`:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
PUT /employees?id=eq.4 HTTP/1.1
|
||||
|
||||
{ "id": 4, "name": "Sara B.", "salary": 60000 }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost/employees?id=eq.4" \
|
||||
-X PUT -H "Content-Type: application/json" \
|
||||
@@ -895,26 +621,13 @@ Delete
|
||||
|
||||
To delete rows in a table, use the DELETE verb plus :ref:`h_filter`. For instance deleting inactive users:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
DELETE /user?active=is.false HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/user?active=is.false" -X DELETE
|
||||
|
||||
Deletions also support :ref:`prefer_return` plus :ref:`v_filter`.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
DELETE /user?id=eq.1 HTTP/1.1
|
||||
Prefer: return=representation
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/user?id=eq.1" -X DELETE \
|
||||
-H "Prefer: return=representation"
|
||||
@@ -934,27 +647,13 @@ 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-tab:: http
|
||||
|
||||
PATCH /users?limit=10&order=id&last_login=lt.2017-01-01 HTTP/1.1
|
||||
|
||||
{ "status": "inactive" }
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
.. code-block:: bash
|
||||
|
||||
curl -X DELETE "http://localhost:3000/users?limit=10&order=id&status=eq.inactive"
|
||||
|
||||
|
||||
@@ -31,13 +31,7 @@ To request this:
|
||||
|
||||
Do this:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /%D9%85%D9%88%D8%A7%D8%B1%D8%AF HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/%D9%85%D9%88%D8%A7%D8%B1%D8%AF"
|
||||
|
||||
@@ -48,13 +42,7 @@ Table / Columns with spaces
|
||||
|
||||
You can request table/columns with spaces in them by percent encoding the spaces with ``%20``:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /Order%20Items?Unit%20Price=lt.200 HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/Order%20Items?Unit%20Price=lt.200"
|
||||
|
||||
@@ -67,25 +55,13 @@ If filters include PostgREST reserved characters(``,``, ``.``, ``:``, ``()``) yo
|
||||
|
||||
Here ``Hebdon,John`` and ``Williams,Mary`` are values.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /employees?name=in.(%22Hebdon,John%22,%22Williams,Mary%22) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/employees?name=in.(%22Hebdon,John%22,%22Williams,Mary%22)"
|
||||
|
||||
Here ``information.cpe`` is a column name.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /vulnerabilities?%22information.cpe%22=like.*MS* HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/vulnerabilities?%22information.cpe%22=like.*MS*"
|
||||
|
||||
@@ -93,13 +69,7 @@ If the value filtered by the ``in`` operator has a double quote (``"``), you can
|
||||
|
||||
Here ``Quote:"`` and ``Backslash:\`` are percent-encoded values. Note that ``%5C`` is the percent-encoded backslash.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /marks?name=in.(%22Quote:%5C%22%22,%22Backslash:%5C%5C%22) HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/marks?name=in.(%22Quote:%5C%22%22,%22Backslash:%5C%5C%22)"
|
||||
|
||||
@@ -107,4 +77,3 @@ Here ``Quote:"`` and ``Backslash:\`` are percent-encoded values. Note that ``%5C
|
||||
|
||||
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`.
|
||||
|
||||
|
||||
@@ -86,14 +86,7 @@ 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-tab:: http
|
||||
|
||||
GET /foo HTTP/1.1
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/foo" \
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4"
|
||||
|
||||
@@ -13,13 +13,7 @@ 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-tab:: http
|
||||
|
||||
GET localhost:3001/live HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl -I "http://localhost:3001/live"
|
||||
|
||||
|
||||
@@ -125,15 +125,7 @@ You can enable tracing HTTP requests by setting :ref:`server-trace-header`. Spec
|
||||
|
||||
server-trace-header = "X-Request-Id"
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /users HTTP/1.1
|
||||
|
||||
X-Request-Id: 123
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/users" \
|
||||
-H "X-Request-Id: 123"
|
||||
@@ -151,13 +143,7 @@ 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-tab:: http
|
||||
|
||||
GET /users HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/users" -i
|
||||
|
||||
@@ -186,14 +172,7 @@ 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-tab:: http
|
||||
|
||||
GET /users?select=name&order=id HTTP/1.1
|
||||
Accept: application/vnd.pgrst.plan
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/users?select=name&order=id" \
|
||||
-H "Accept: application/vnd.pgrst.plan"
|
||||
@@ -205,14 +184,7 @@ 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-tab:: http
|
||||
|
||||
GET /users?select=name&order=id HTTP/1.1
|
||||
Accept: application/vnd.pgrst.plan+json
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/users?select=name&order=id" \
|
||||
-H "Accept: application/vnd.pgrst.plan+json"
|
||||
|
||||
@@ -30,13 +30,7 @@ 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-tab:: http
|
||||
|
||||
GET /callcounter HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/callcounter"
|
||||
|
||||
@@ -246,13 +240,7 @@ You can set the ``response.status`` to override the default status code PostgRES
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: http
|
||||
|
||||
GET /rpc/teapot HTTP/1.1
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/rpc/teapot" -i
|
||||
|
||||
@@ -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-tab:: http
|
||||
|
||||
GET /people HTTP/1.1
|
||||
User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)
|
||||
|
||||
.. code-tab:: bash Curl
|
||||
.. code-block:: bash
|
||||
|
||||
curl "http://localhost:3000/people" -i \
|
||||
-H "User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)"
|
||||
|
||||
Reference in New Issue
Block a user