From bed1013ecd5334b0bf8a6ee8abaa2b6c63aed551 Mon Sep 17 00:00:00 2001 From: steve-chavez Date: Wed, 14 Aug 2019 21:49:49 -0500 Subject: [PATCH] Fix #235, casting type to json object --- api.rst | 8 ++ how-tos/casting-type-to-custom-json.rst | 95 +++++++++++++++++++ .../embedding-table-from-another-schema.rst | 2 +- index.rst | 1 + 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 how-tos/casting-type-to-custom-json.rst diff --git a/api.rst b/api.rst index 7c9ed9b9e..ca8212c3e 100644 --- a/api.rst +++ b/api.rst @@ -158,6 +158,9 @@ When certain columns are wide (such as those holding binary data), it is more ef The default is :sql:`*`, meaning all columns. This value will become more important below in :ref:`resource_embedding`. +Renaming Columns +~~~~~~~~~~~~~~~~ + You can rename the columns by prefixing them with an alias followed by the colon ``:`` operator. .. code-block:: http @@ -169,6 +172,11 @@ You can rename the columns by prefixing them with an alias followed by the colon {"fullName": "Jane Doe", "birthDate": "01/12/1998"} ] +.. _casting_columns: + +Casting Columns +~~~~~~~~~~~~~~~ + Casting the columns is possible by suffixing them with the double colon ``::`` plus the desired type. .. code-block:: http diff --git a/how-tos/casting-type-to-custom-json.rst b/how-tos/casting-type-to-custom-json.rst new file mode 100644 index 000000000..f9d13afa7 --- /dev/null +++ b/how-tos/casting-type-to-custom-json.rst @@ -0,0 +1,95 @@ +Casting a type to a custom JSON object +====================================== + +While using PostgREST you might have noticed that certain PostgreSQL types translate to JSON strings when you would +have expected a JSON object or array. For example, let's see the case of `range types `_. + +.. code-block:: postgres + + -- example taken from https://www.postgresql.org/docs/11/rangetypes.html#RANGETYPES-EXAMPLES + create table reservations ( + room int + , during tsrange + ); + + insert into + reservations + values + (1108, tsrange('2010-01-01 14:30', '2010-01-01 15:30')); + +Here we have a column named **during** as a ``tsrange`` type, we would like to get it as JSON through PostgREST. + +.. code-block:: bash + + curl "http://localhost:3000/reservations" + +Result: + +.. code-block:: json + + [ + { + "room":1108, + "during":"[\"2010-01-01 14:30:00\",\"2010-01-01 15:30:00\")" + } + ] + +The **during** value is probably not the in the format you want. We get a JSON string because by default PostgreSQL casts +the type to JSON by using its ``text`` representation. We can change this representation to a custom JSON object by `creating a CAST `_ . + +To do this, first we'll define the function that will do the conversion from ``tsrange`` to ``json``. + +.. code-block:: postgres + + create or replace function tsrange_to_json(tsrange) returns json as $$ + select json_build_object( + 'lower', lower($1) + , 'upper', upper($1) + , 'lower_inc', lower_inc($1) + , 'upper_inc', upper_inc($1) + ); + $$ language sql; + +Using this function we'll create the CAST. + +.. code-block:: postgres + + create cast (tsrange as json) with function tsrange_to_json(tsrange) as assignment; + +And we'll do the request and :ref:`cast the column `. + +.. code-block:: bash + + curl "http://localhost:3000/reservations?select=room,during::json" + +The result now is: + +.. code-block:: json + + [ + { + "room":1108, + "during":{ + "lower" : "2010-01-01T14:30:00", + "upper" : "2010-01-01T15:30:00", + "lower_inc" : true, + "upper_inc" : false + } + } + ] + +You can use the same idea for creating custom CASTs for different types. + +.. note:: + + If you don't want to modify CASTs for built-in types, an option would be to `create a custom type `_ + for your own ``tsrange`` and add its own CAST. + + .. code-block:: postgres + + create type mytsrange as range (subtype = timestamp, subtype_diff = tsrange_subdiff); + + -- define column types and casting function analoguously to the above example + -- ... + + create cast (mytsrange as json) with function mytsrange_to_json(mytsrange) as assignment; diff --git a/how-tos/embedding-table-from-another-schema.rst b/how-tos/embedding-table-from-another-schema.rst index 751706464..60265dd40 100644 --- a/how-tos/embedding-table-from-another-schema.rst +++ b/how-tos/embedding-table-from-another-schema.rst @@ -16,7 +16,7 @@ And you want to :ref:`embed ` the **people** table with a ** create schema if not exists private; - -- For simplicity's sake the table is devoid of constraints on email, phone, etc. + -- For simplicity's sake the table is devoid of constraints/domains on email, phone, etc. create table private.details( id int primary key references public.people , email text diff --git a/index.rst b/index.rst index f8649000d..8f6bdf28f 100644 --- a/index.rst +++ b/index.rst @@ -110,6 +110,7 @@ Translations :titlesonly: how-tos/embedding-table-from-another-schema.rst + how-tos/casting-type-to-custom-json.rst .. toctree:: :caption: Integrations