Life Altering PostgreSQL Patterns
mccue.dev
mccue.dev
I've not seen this approach documented much online - but it works really well for me. It has the advantage of keeping all my tables flat, while still being able to encode business logic into the database.
A typical query I might type, would look something like..
`SELECT ,trip_start_date(id) FROM trips WHERE trip2region(id) = 'AU'`
Where the two macros are just simple table joins, saving me the boilerplate work. Where this approach has really shined, though, is through function composition...
`SELECT FROM trips WHERE loc2region(trip_origin(id)) NOT IN loc2region(location_is_hotel(trip_locations_visited(id)))`
So something like the above, which is a mix of scalar and table functions, would give me all the trips where the traveler stayed in hotels outside of their home region. Maybe not the best example, because I don't actually work with trip/hotel/travel data at all, but I'd be interested reading more about this approach. I was surprised how well-optimized the queries are.... \endyap
Thats the only reason I didn't mention it, seemed a bit of a rabbit hole.
For the "Mechanically name join tables" point, I would at least put a tiny bit of effort into their names, rather than zero. For example, using a naming convention to make that kind of table instantly recognisable, e.g. 'person_x_pet' instead of just 'person_pet'.
This is a problem with the `alter` abilities, but in fact the lack of using `views` is a problem.
`views` is how you abstract the database. Also, combined with `instead of` triggers become amazing to simplify the other triggers.
Nothing more awesome than flatten your db so external code barely ever do joins themselves.
My trick to solve the problem of migrations is that I put all the `views, functions, etc` in their own section of a `sql` file:
-- DEPS --
-- VIEWS
-- FUNCTIONS
-- TRIGGERS
And then I have a special `DROP ALL VIEWS, CREATE ALL VIEWS` comment in my migrations that do that. It remove the problem greatly!
Dropping a view can work, but not when the system is under load (found that out the hard way.) I'm not saying its the worst possible situation, just a greater burden than you would expect going into it.
Can you elaborate on `instead of` triggers? How do you make use of those?
That doesn't inspire confidence in the longevity of their offering - but i'm also unclear exactly what it is they are offering. Can you give the audience the pitch?
This has been solved already in more than one way (UUIDv7, ULIDs, Snowflake IDs to name a few).