I love the RESTful API generated automatically by PostgREST from my Supabase PostgreSQL schema. However, at the beginning I did have concerns about how I could handle more complex queries … that was at least until I read more about PostgreSQL Functions and how to build them in Supabase!
This is the Netlify deploy data dashboard I was working towards building and I wanted to avoid introducing a calendar datepicker interface but rather only show the the years and months I had build data for from my deploys. Below is a table representing my database columns with some sample data for a row
id | 1 |
---|---|
deploy_id | xxxxxxxxxx |
branch | main |
context | production |
deploy_time | 38 |
created_at | 2021-07-22T18:11:31.959+00:00 |
What I wanted was to query the database and return a column of unique years present in the created_at
column. Additionally, for each year I wanted another column consisting of an array of unique months and I could use this to build out the buttons on the dashboard interface. Essentially the result on my dummy data would look similar to the following
years | month_numbers |
---|---|
2020 | {9,10,11,12} |
2021 | {1,2,3,4,5,6,7} |
I could write the following SQL query to generate this result
SELECT
distinct(EXTRACT(YEAR FROM created_at)) AS year,
array_agg(distinct(EXTRACT(MONTH FROM created_at))) AS month_numbers
FROM public.netlify_deploy_data
GROUP BY year
ORDER BY year ASC
but the problem was using the JavaScript Supabase client to create the query. I'm not sure this can be done through the client but that was when I read about PostgreSQL Functions in Supabase and saw how it could simplify things for me.
I think this is a fairly new addition to Supabase but I found it really straight forward to use. In your Supabase dashboard for your organisation, navigate to /database/functions
where you can create a new function.
First up, give your function a name (netlify_deploy_data_years_and_months in my case) and next select a return type. Now, this is where I encountered another brief stumbling block because I could only return a single record or a value of a certain type from what I could see. However, I did see the option for returning JSON and I figured if I could wrap my SQL query to return JSON then I could use that no matter how many records I had. After playing with the queries locally I managed to get things working with the following
SELECT array_to_json(array_agg(row_to_json(t)))
FROM (
SELECT
distinct(EXTRACT(YEAR FROM created_at)) AS year,
array_agg(distinct(EXTRACT(MONTH FROM created_at))) AS month_numbers
FROM public.netlify_deploy_data
GROUP BY year
ORDER BY year ASC
)t;
which gives me back
[{"year":2020,"month_numbers":[9,10,11,12]}, {"year":2021,"month_numbers":[1,2,3,4,5,6,7]}]
and now I could use the JSON return type for my function.
In order to add this SQL to the function rather than using plpgsql, I had to click the toggle for show advanced settings
and change the language to sql. Now you can add the SQL snippet from above to the Definition
section.
This now makes it really easy to query using the JavaScript client with the following
const { data, error } = await supabase
.rpc("netlify_deploy_data_years_and_months")
As I use Supabase more, I'm finding more functionality and I have to say that I'm really impressed with what I've seen, it's a fantastic product.